From 43cd0b22b523f52508cf77942da721432711b850 Mon Sep 17 00:00:00 2001 From: amandalund Date: Fri, 10 Mar 2017 15:13:08 -0600 Subject: [PATCH 01/18] Added global filter variables; Read in filters separately in input XML --- src/global.F90 | 10 +- src/input_xml.F90 | 795 ++++++++++++++++++++---------------- src/tally_filter_header.F90 | 1 + src/tally_header.F90 | 6 +- 4 files changed, 447 insertions(+), 365 deletions(-) diff --git a/src/global.F90 b/src/global.F90 index c48367214..027cf1b15 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -21,6 +21,7 @@ module global use surface_header, only: SurfaceContainer use source_header, only: SourceDistribution use tally_header, only: TallyObject, TallyDerivative + use tally_filter_header, only: TallyFilterContainer use trigger_header, only: KTrigger use timer_header, only: Timer use volume_header, only: VolumeCalculation @@ -57,6 +58,7 @@ module global type(DictIntInt) :: surface_dict type(DictIntInt) :: material_dict type(DictIntInt) :: mesh_dict + type(DictIntInt) :: filter_dict type(DictIntInt) :: tally_dict type(DictIntInt) :: plot_dict @@ -138,7 +140,8 @@ module global ! TALLY-RELATED VARIABLES type(RegularMesh), allocatable, target :: meshes(:) - type(TallyObject), allocatable, target :: tallies(:) + type(TallyObject), allocatable, target :: tallies(:) + type(TallyFilterContainer), allocatable :: filters(:) integer, allocatable :: matching_bins(:) real(8), allocatable :: filter_weights(:) @@ -182,6 +185,8 @@ module global integer :: n_meshes = 0 ! # of structured meshes integer :: n_user_meshes = 0 ! # of structured user meshes + integer :: n_filters = 0 ! # of filters + integer :: n_user_filters = 0 ! # of user filters integer :: n_tallies = 0 ! # of tallies integer :: n_user_tallies = 0 ! # of user tallies @@ -373,6 +378,7 @@ module global ! User-defined tally information integer :: n_cmfd_meshes = 1 ! # of structured meshes + integer :: n_cmfd_filters = 1 ! # of filters integer :: n_cmfd_tallies = 3 ! # of user-defined tallies ! Adjoint method type @@ -494,6 +500,7 @@ contains ! Deallocate tally-related arrays if (allocated(global_tallies)) deallocate(global_tallies) if (allocated(meshes)) deallocate(meshes) + if (allocated(filters)) deallocate(filters) if (allocated(tallies)) deallocate(tallies) if (allocated(matching_bins)) deallocate(matching_bins) if (allocated(filter_weights)) deallocate(filter_weights) @@ -531,6 +538,7 @@ contains call surface_dict % clear() call material_dict % clear() call mesh_dict % clear() + call filter_dict % clear() call tally_dict % clear() call plot_dict % clear() call nuclide_dict % clear() diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 163dcf901..2f1ab2a55 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -28,6 +28,7 @@ module input_xml starts_with, ends_with, tokenize, split_string, & zero_padded use tally_header, only: TallyObject + use tally_filter_header, only: TallyFilterContainer use tally_filter use tally_initialize, only: add_tallies use xml_interface @@ -2613,9 +2614,10 @@ contains integer :: l ! another loop index integer :: id ! user-specified identifier integer :: i_mesh ! index in meshes array + integer :: i_filt ! index in filters array integer :: n ! size of arrays in mesh specification integer :: n_words ! number of words read - integer :: n_filters ! number of filters + integer :: n_filter ! number of filters integer :: n_new ! number of new scores to add based on Yn/Pn tally integer :: n_scores ! number of tot scores after adjusting for Yn/Pn tally integer :: n_bins ! total new bins for this score @@ -2633,6 +2635,7 @@ contains integer :: Nangle ! Number of angular bins real(8) :: dangle ! Mu spacing if using automatic allocation integer :: iangle ! Loop counter for building mu filter bins + integer, allocatable :: temp_filter(:) ! temporary filter indices character(MAX_LINE_LEN) :: filename character(MAX_WORD_LEN) :: word character(MAX_WORD_LEN) :: score_name @@ -2640,9 +2643,10 @@ contains character(MAX_WORD_LEN), allocatable :: sarray(:) type(DictCharInt) :: trigger_scores type(ElemKeyValueCI), pointer :: pair_list - type(TallyObject), pointer :: t + type(TallyObject), pointer :: t + type(TallyFilterContainer), pointer :: f type(RegularMesh), pointer :: m - type(TallyFilterContainer), allocatable :: filters(:) ! temporary filters + type(TallyFilterContainer), allocatable :: temp_filters(:) type(XMLDocument) :: doc type(XMLNode) :: root type(XMLNode) :: node_mesh @@ -2685,6 +2689,9 @@ contains ! Get pointer list to XML call get_node_list(root, "mesh", node_mesh_list) + ! Get pointer list to XML + call get_node_list(root, "filter", node_filt_list) + ! Get pointer list to XML call get_node_list(root, "tally", node_tal_list) @@ -2699,6 +2706,17 @@ contains ! Allocate mesh array if (n_meshes > 0) allocate(meshes(n_meshes)) + ! Check for user filters + n_user_filters = size(node_filt_list) + if (cmfd_run) then + n_filters = n_user_filters + n_cmfd_filters + else + n_filters = n_user_filters + end if + + ! Allocate filters array + if (n_user_filters > 0) allocate(filters(n_filters)) + ! Check for user tallies n_user_tallies = size(node_tal_list) if (n_user_tallies == 0) then @@ -2932,6 +2950,356 @@ contains end associate end do + ! ========================================================================== + ! READ FILTER DATA + + READ_FILTERS: do i = 1, n_user_filters + f => filters(i) + + ! Get pointer to filter xml node + node_filt = node_filt_list(i) + + ! Copy filter id + if (check_for_node(node_filt, "id")) then + call get_node_value(node_filt, "id", f % id) + else + call fatal_error("Must specify id for filter in tally XML file.") + end if + + ! Check to make sure 'id' hasn't been used + if (filter_dict % has_key(f % id)) then + call fatal_error("Two or more filters use the same unique ID: " & + // to_str(f % id)) + end if + + ! Convert filter type to lower case + temp_str = '' + if (check_for_node(node_filt, "type")) & + call get_node_value(node_filt, "type", temp_str) + temp_str = to_lower(temp_str) + + ! Determine number of bins + select case(temp_str) + case ("energy", "energyout", "mu", "polar", "azimuthal") + if (.not. check_for_node(node_filt, "bins")) then + call fatal_error("Bins not set in filter " // trim(to_str(f % id))) + end if + n_words = node_word_count(node_filt, "bins") + case ("mesh", "universe", "material", "cell", "distribcell", & + "cellborn", "surface", "delayedgroup") + if (.not. check_for_node(node_filt, "bins")) then + call fatal_error("Bins not set in filter " // trim(to_str(f % id))) + end if + n_words = node_word_count(node_filt, "bins") + end select + + ! Determine type of filter + select case (temp_str) + + case ('distribcell') + ! Allocate and declare the filter type + allocate(DistribcellFilter::f % obj) + select type (filt => f % obj) + type is (DistribcellFilter) + if (n_words /= 1) call fatal_error("Only one cell can be & + &specified per distribcell filter.") + ! Store bins + call get_node_value(node_filt, "bins", filt % cell) + end select + + case ('cell') + ! Allocate and declare the filter type + allocate(CellFilter::f % obj) + select type (filt => f % obj) + type is (CellFilter) + ! Allocate and store bins + filt % n_bins = n_words + allocate(filt % cells(n_words)) + call get_node_array(node_filt, "bins", filt % cells) + end select + + case ('cellborn') + ! Allocate and declare the filter type + allocate(CellbornFilter::f % obj) + select type (filt => f % obj) + type is (CellbornFilter) + ! Allocate and store bins + filt % n_bins = n_words + allocate(filt % cells(n_words)) + call get_node_array(node_filt, "bins", filt % cells) + end select + + case ('material') + ! Allocate and declare the filter type + allocate(MaterialFilter::f % obj) + select type (filt => f % obj) + type is (MaterialFilter) + ! Allocate and store bins + filt % n_bins = n_words + allocate(filt % materials(n_words)) + call get_node_array(node_filt, "bins", filt % materials) + end select + + case ('universe') + ! Allocate and declare the filter type + allocate(UniverseFilter::f % obj) + select type (filt => f % obj) + type is (UniverseFilter) + ! Allocate and store bins + filt % n_bins = n_words + allocate(filt % universes(n_words)) + call get_node_array(node_filt, "bins", filt % universes) + end select + + case ('surface') + call fatal_error("Surface filter is not yet supported!") + ! Allocate and declare the filter type + allocate(SurfaceFilter::f % obj) + select type (filt => f % obj) + type is (SurfaceFilter) + ! Allocate and store bins + filt % n_bins = n_words + allocate(filt % surfaces(n_words)) + call get_node_array(node_filt, "bins", filt % surfaces) + end select + + case ('mesh') + ! Allocate and declare the filter type + allocate(MeshFilter::f % obj) + select type (filt => f % obj) + type is (MeshFilter) + if (n_words /= 1) call fatal_error("Only one mesh can be & + &specified per mesh filter.") + + ! Determine id of mesh + call get_node_value(node_filt, "bins", id) + + ! Get pointer to mesh + if (mesh_dict % has_key(id)) then + i_mesh = mesh_dict % get_key(id) + m => meshes(i_mesh) + else + call fatal_error("Could not find mesh " // trim(to_str(id)) & + // " specified on filter " // trim(to_str(f % id))) + end if + + ! Determine number of bins + filt % n_bins = product(m % dimension) + + ! Store the index of the mesh + filt % mesh = i_mesh + end select + + case ('energy') + + ! Allocate and declare the filter type + allocate(EnergyFilter::f % obj) + select type (filt => f % obj) + type is (EnergyFilter) + ! Allocate and store bins + filt % n_bins = n_words - 1 + allocate(filt % bins(n_words)) + call get_node_array(node_filt, "bins", filt % bins) + + ! We can save tallying time if we know that the tally bins match + ! the energy group structure. In that case, the matching bin + ! index is simply the group (after flipping for the different + ! ordering of the library and tallying systems). + if (.not. run_CE) then + if (n_words == num_energy_groups + 1) then + if (all(filt % bins == energy_bins(num_energy_groups + 1:1:-1))) & + then + filt % matches_transport_groups = .true. + end if + end if + end if + end select + + case ('energyout') + ! Allocate and declare the filter type + allocate(EnergyoutFilter::f % obj) + select type (filt => f % obj) + type is (EnergyoutFilter) + ! Allocate and store bins + filt % n_bins = n_words - 1 + allocate(filt % bins(n_words)) + call get_node_array(node_filt, "bins", filt % bins) + + ! We can save tallying time if we know that the tally bins match + ! the energy group structure. In that case, the matching bin + ! index is simply the group (after flipping for the different + ! ordering of the library and tallying systems). + if (.not. run_CE) then + if (n_words == num_energy_groups + 1) then + if (all(filt % bins == energy_bins(num_energy_groups + 1:1:-1))) & + then + filt % matches_transport_groups = .true. + end if + end if + end if + end select + + case ('delayedgroup') + + ! Allocate and declare the filter type + allocate(DelayedGroupFilter::f % obj) + select type (filt => f % obj) + type is (DelayedGroupFilter) + ! Allocate and store bins + filt % n_bins = n_words + allocate(filt % groups(n_words)) + call get_node_array(node_filt, "bins", filt % groups) + + ! Check that bins are all are between 1 and MAX_DELAYED_GROUPS + do d = 1, n_words + if (filt % groups(d) < 1 .or. & + filt % groups(d) > MAX_DELAYED_GROUPS) then + call fatal_error("Encountered delayedgroup bin with index " & + // trim(to_str(filt % groups(d))) // " that is outside & + &the range of 1 to MAX_DELAYED_GROUPS ( " & + // trim(to_str(MAX_DELAYED_GROUPS)) // ")") + end if + end do + end select + + case ('mu') + ! Allocate and declare the filter type + allocate(MuFilter::f % obj) + select type (filt => f % obj) + type is (MuFilter) + ! Allocate and store bins + filt % n_bins = n_words - 1 + allocate(filt % bins(n_words)) + call get_node_array(node_filt, "bins", filt % bins) + + ! Allow a user to input a lone number which will mean that you + ! subdivide [-1,1] evenly with the input being the number of bins + if (n_words == 1) then + Nangle = int(filt % bins(1)) + if (Nangle > 1) then + filt % n_bins = Nangle + dangle = TWO / real(Nangle,8) + deallocate(filt % bins) + allocate(filt % bins(Nangle + 1)) + do iangle = 1, Nangle + filt % bins(iangle) = -ONE + (iangle - 1) * dangle + end do + filt % bins(Nangle + 1) = ONE + else + call fatal_error("Number of bins for mu filter must be& + & greater than 1 on filter " & + // trim(to_str(f % id)) // ".") + end if + end if + end select + + case ('polar') + ! Allocate and declare the filter type + allocate(PolarFilter::f % obj) + select type (filt => f % obj) + type is (PolarFilter) + ! Allocate and store bins + filt % n_bins = n_words - 1 + allocate(filt % bins(n_words)) + call get_node_array(node_filt, "bins", filt % bins) + + ! Allow a user to input a lone number which will mean that you + ! subdivide [0,pi] evenly with the input being the number of bins + if (n_words == 1) then + Nangle = int(filt % bins(1)) + if (Nangle > 1) then + filt % n_bins = Nangle + dangle = PI / real(Nangle,8) + deallocate(filt % bins) + allocate(filt % bins(Nangle + 1)) + do iangle = 1, Nangle + filt % bins(iangle) = (iangle - 1) * dangle + end do + filt % bins(Nangle + 1) = PI + else + call fatal_error("Number of bins for polar filter must be& + & greater than 1 on filter " & + // trim(to_str(f % id)) // ".") + end if + end if + end select + + case ('azimuthal') + ! Allocate and declare the filter type + allocate(AzimuthalFilter::f % obj) + select type (filt => f % obj) + type is (AzimuthalFilter) + ! Allocate and store bins + filt % n_bins = n_words - 1 + allocate(filt % bins(n_words)) + call get_node_array(node_filt, "bins", filt % bins) + + ! Allow a user to input a lone number which will mean that you + ! subdivide [-pi,pi) evenly with the input being the number of + ! bins + if (n_words == 1) then + Nangle = int(filt % bins(1)) + if (Nangle > 1) then + filt % n_bins = Nangle + dangle = TWO * PI / real(Nangle,8) + deallocate(filt % bins) + allocate(filt % bins(Nangle + 1)) + do iangle = 1, Nangle + filt % bins(iangle) = -PI + (iangle - 1) * dangle + end do + filt % bins(Nangle + 1) = PI + else + call fatal_error("Number of bins for azimuthal filter must be& + & greater than 1 on filter " & + // trim(to_str(f % id)) // ".") + end if + end if + end select + + case ('energyfunction') + ! Allocate and declare the filter type. + allocate(EnergyFunctionFilter::f % obj) + select type (filt => f % obj) + type is (EnergyFunctionFilter) + filt % n_bins = 1 + ! Make sure this is continuous-energy mode. + if (.not. run_CE) then + call fatal_error("EnergyFunction filters are only supported for & + &continuous-energy transport calculations") + end if + + ! Allocate and store energy grid. + if (.not. check_for_node(node_filt, "energy")) then + call fatal_error("Energy grid not specified for EnergyFunction & + &filter on filter " // trim(to_str(f % id))) + end if + n_words = node_word_count(node_filt, "energy") + allocate(filt % energy(n_words)) + call get_node_array(node_filt, "energy", filt % energy) + + ! Allocate and store interpolant values. + if (.not. check_for_node(node_filt, "y")) then + call fatal_error("y values not specified for EnergyFunction & + &filter on filter " // trim(to_str(f % id))) + end if + n_words = node_word_count(node_filt, "y") + allocate(filt % y(n_words)) + call get_node_array(node_filt, "y", filt % y) + end select + + case default + ! Specified filter is invalid, raise error + call fatal_error("Unknown filter type '" & + // trim(temp_str) // "' on filter " & + // trim(to_str(f % id)) // ".") + + end select + + ! Add filter to dictionary + call filter_dict % add_key(f % id, i) + + end do READ_FILTERS + ! ========================================================================== ! READ TALLY DATA @@ -2973,378 +3341,70 @@ contains ! ======================================================================= ! READ DATA FOR FILTERS - ! Get pointer list to XML and get number of filters - call get_node_list(node_tal, "filter", node_filt_list) - n_filters = size(node_filt_list) + ! Determine number of filters + if (check_for_node(node_tal, "filters")) then + n_filter = node_word_count(node_tal, "filters") + else + n_filter = 0 + end if - ! Allocate filters array - allocate(t % filters(n_filters)) + ! Allocate and store filter user ids + allocate(temp_filter(n_filter)) + call get_node_array(node_tal, "filters", temp_filter) - READ_FILTERS: do j = 1, n_filters - ! Get pointer to filter xml node - node_filt = node_filt_list(j) + do j = 1, n_filter + ! Get pointer to filter + if (filter_dict % has_key(temp_filter(j))) then + i_filt = filter_dict % get_key(temp_filter(j)) + f => filters(i_filt) + else + call fatal_error("Could not find filter " & + // trim(to_str(temp_filter(j))) & // " specified on tally " & + // trim(to_str(t % id))) + end if - ! Convert filter type to lower case - temp_str = '' - if (check_for_node(node_filt, "type")) & - call get_node_value(node_filt, "type", temp_str) - temp_str = to_lower(temp_str) - - ! Determine number of bins - select case(temp_str) - case ("energy", "energyout", "mu", "polar", "azimuthal") - if (.not. check_for_node(node_filt, "bins")) then - call fatal_error("Bins not set in filter on tally " & - // trim(to_str(t % id))) - end if - n_words = node_word_count(node_filt, "bins") - case ("mesh", "universe", "material", "cell", "distribcell", & - "cellborn", "surface", "delayedgroup") - if (.not. check_for_node(node_filt, "bins")) then - call fatal_error("Bins not set in filter on tally " & - // trim(to_str(t % id))) - end if - n_words = node_word_count(node_filt, "bins") - end select - - ! Determine type of filter - select case (temp_str) - - case ('distribcell') - ! Allocate and declare the filter type - allocate(DistribcellFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (DistribcellFilter) - if (n_words /= 1) call fatal_error("Only one cell can be & - &specified per distribcell filter.") - ! Store bins - call get_node_value(node_filt, "bins", filt % cell) - end select - ! Set the filter index in the tally find_filter array + ! Set the filter index in the tally find_filter array + select type (f % obj) + type is (DistribcellFilter) t % find_filter(FILTER_DISTRIBCELL) = j - - case ('cell') - ! Allocate and declare the filter type - allocate(CellFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (CellFilter) - ! Allocate and store bins - filt % n_bins = n_words - allocate(filt % cells(n_words)) - call get_node_array(node_filt, "bins", filt % cells) - end select - ! Set the filter index in the tally find_filter array + type is (CellFilter) t % find_filter(FILTER_CELL) = j - - case ('cellborn') - ! Allocate and declare the filter type - allocate(CellbornFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (CellbornFilter) - ! Allocate and store bins - filt % n_bins = n_words - allocate(filt % cells(n_words)) - call get_node_array(node_filt, "bins", filt % cells) - end select - ! Set the filter index in the tally find_filter array + type is (CellbornFilter) t % find_filter(FILTER_CELLBORN) = j - - case ('material') - ! Allocate and declare the filter type - allocate(MaterialFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (MaterialFilter) - ! Allocate and store bins - filt % n_bins = n_words - allocate(filt % materials(n_words)) - call get_node_array(node_filt, "bins", filt % materials) - end select - ! Set the filter index in the tally find_filter array + type is (MaterialFilter) t % find_filter(FILTER_MATERIAL) = j - - case ('universe') - ! Allocate and declare the filter type - allocate(UniverseFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (UniverseFilter) - ! Allocate and store bins - filt % n_bins = n_words - allocate(filt % universes(n_words)) - call get_node_array(node_filt, "bins", filt % universes) - end select - ! Set the filter index in the tally find_filter array + type is (UniverseFilter) t % find_filter(FILTER_UNIVERSE) = j - - case ('surface') - call fatal_error("Surface filter is not yet supported!") - ! Allocate and declare the filter type - allocate(SurfaceFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (SurfaceFilter) - ! Allocate and store bins - filt % n_bins = n_words - allocate(filt % surfaces(n_words)) - call get_node_array(node_filt, "bins", filt % surfaces) - end select - ! Set the filter index in the tally find_filter array + type is (SurfaceFilter) t % find_filter(FILTER_SURFACE) = j - - case ('mesh') - ! Allocate and declare the filter type - allocate(MeshFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (MeshFilter) - if (n_words /= 1) call fatal_error("Only one mesh can be & - &specified per mesh filter.") - - ! Determine id of mesh - call get_node_value(node_filt, "bins", id) - - ! Get pointer to mesh - if (mesh_dict % has_key(id)) then - i_mesh = mesh_dict % get_key(id) - m => meshes(i_mesh) - else - call fatal_error("Could not find mesh " // trim(to_str(id)) & - // " specified on tally " // trim(to_str(t % id))) - end if - - ! Determine number of bins - filt % n_bins = product(m % dimension) - - ! Store the index of the mesh - filt % mesh = i_mesh - end select - - ! Set the filter index in the tally find_filter array + type is (MeshFilter) t % find_filter(FILTER_MESH) = j - - case ('energy') - - ! Allocate and declare the filter type - allocate(EnergyFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (EnergyFilter) - ! Allocate and store bins - filt % n_bins = n_words - 1 - allocate(filt % bins(n_words)) - call get_node_array(node_filt, "bins", filt % bins) - - ! We can save tallying time if we know that the tally bins match - ! the energy group structure. In that case, the matching bin - ! index is simply the group (after flipping for the different - ! ordering of the library and tallying systems). - if (.not. run_CE) then - if (n_words == num_energy_groups + 1) then - if (all(filt % bins == energy_bins(num_energy_groups + 1:1:-1))) & - then - filt % matches_transport_groups = .true. - end if - end if - end if - end select - ! Set the filter index in the tally find_filter array + type is (EnergyFilter) t % find_filter(FILTER_ENERGYIN) = j - - case ('energyout') - ! Allocate and declare the filter type - allocate(EnergyoutFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (EnergyoutFilter) - ! Allocate and store bins - filt % n_bins = n_words - 1 - allocate(filt % bins(n_words)) - call get_node_array(node_filt, "bins", filt % bins) - - ! We can save tallying time if we know that the tally bins match - ! the energy group structure. In that case, the matching bin - ! index is simply the group (after flipping for the different - ! ordering of the library and tallying systems). - if (.not. run_CE) then - if (n_words == num_energy_groups + 1) then - if (all(filt % bins == energy_bins(num_energy_groups + 1:1:-1))) & - then - filt % matches_transport_groups = .true. - end if - end if - end if - end select - ! Set the filter index in the tally find_filter array + type is (EnergyoutFilter) t % find_filter(FILTER_ENERGYOUT) = j - ! Set to analog estimator t % estimator = ESTIMATOR_ANALOG - - case ('delayedgroup') - - ! Allocate and declare the filter type - allocate(DelayedGroupFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (DelayedGroupFilter) - ! Allocate and store bins - filt % n_bins = n_words - allocate(filt % groups(n_words)) - call get_node_array(node_filt, "bins", filt % groups) - - ! Check that bins are all are between 1 and MAX_DELAYED_GROUPS - do d = 1, n_words - if (filt % groups(d) < 1 .or. & - filt % groups(d) > MAX_DELAYED_GROUPS) then - call fatal_error("Encountered delayedgroup bin with index " & - // trim(to_str(filt % groups(d))) // " that is outside & - &the range of 1 to MAX_DELAYED_GROUPS ( " & - // trim(to_str(MAX_DELAYED_GROUPS)) // ")") - end if - end do - end select - ! Set the filter index in the tally find_filter array + type is (DelayedGroupFilter) t % find_filter(FILTER_DELAYEDGROUP) = j - - case ('mu') - ! Allocate and declare the filter type - allocate(MuFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (MuFilter) - ! Allocate and store bins - filt % n_bins = n_words - 1 - allocate(filt % bins(n_words)) - call get_node_array(node_filt, "bins", filt % bins) - - ! Allow a user to input a lone number which will mean that you - ! subdivide [-1,1] evenly with the input being the number of bins - if (n_words == 1) then - Nangle = int(filt % bins(1)) - if (Nangle > 1) then - filt % n_bins = Nangle - dangle = TWO / real(Nangle,8) - deallocate(filt % bins) - allocate(filt % bins(Nangle + 1)) - do iangle = 1, Nangle - filt % bins(iangle) = -ONE + (iangle - 1) * dangle - end do - filt % bins(Nangle + 1) = ONE - else - call fatal_error("Number of bins for mu filter must be& - & greater than 1 on tally " & - // trim(to_str(t % id)) // ".") - end if - end if - end select - ! Set the filter index in the tally find_filter array + type is (MuFilter) t % find_filter(FILTER_MU) = j - ! Set to analog estimator t % estimator = ESTIMATOR_ANALOG - - case ('polar') - ! Allocate and declare the filter type - allocate(PolarFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (PolarFilter) - ! Allocate and store bins - filt % n_bins = n_words - 1 - allocate(filt % bins(n_words)) - call get_node_array(node_filt, "bins", filt % bins) - - ! Allow a user to input a lone number which will mean that you - ! subdivide [0,pi] evenly with the input being the number of bins - if (n_words == 1) then - Nangle = int(filt % bins(1)) - if (Nangle > 1) then - filt % n_bins = Nangle - dangle = PI / real(Nangle,8) - deallocate(filt % bins) - allocate(filt % bins(Nangle + 1)) - do iangle = 1, Nangle - filt % bins(iangle) = (iangle - 1) * dangle - end do - filt % bins(Nangle + 1) = PI - else - call fatal_error("Number of bins for polar filter must be& - & greater than 1 on tally " & - // trim(to_str(t % id)) // ".") - end if - end if - end select - ! Set the filter index in the tally find_filter array + type is (PolarFilter) t % find_filter(FILTER_POLAR) = j - - case ('azimuthal') - ! Allocate and declare the filter type - allocate(AzimuthalFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (AzimuthalFilter) - ! Allocate and store bins - filt % n_bins = n_words - 1 - allocate(filt % bins(n_words)) - call get_node_array(node_filt, "bins", filt % bins) - - ! Allow a user to input a lone number which will mean that you - ! subdivide [-pi,pi) evenly with the input being the number of - ! bins - if (n_words == 1) then - Nangle = int(filt % bins(1)) - if (Nangle > 1) then - filt % n_bins = Nangle - dangle = TWO * PI / real(Nangle,8) - deallocate(filt % bins) - allocate(filt % bins(Nangle + 1)) - do iangle = 1, Nangle - filt % bins(iangle) = -PI + (iangle - 1) * dangle - end do - filt % bins(Nangle + 1) = PI - else - call fatal_error("Number of bins for azimuthal filter must be& - & greater than 1 on tally " & - // trim(to_str(t % id)) // ".") - end if - end if - end select - ! Set the filter index in the tally find_filter array + type is (AzimuthalFilter) t % find_filter(FILTER_AZIMUTHAL) = j - - case ('energyfunction') - ! Allocate and declare the filter type. - allocate(EnergyFunctionFilter::t % filters(j) % obj) - select type (filt => t % filters(j) % obj) - type is (EnergyFunctionFilter) - filt % n_bins = 1 - ! Make sure this is continuous-energy mode. - if (.not. run_CE) then - call fatal_error("EnergyFunction filters are only supported for & - &continuous-energy transport calculations") - end if - - ! Allocate and store energy grid. - if (.not. check_for_node(node_filt, "energy")) then - call fatal_error("Energy grid not specified for EnergyFunction & - &filter on tally " // trim(to_str(t % id))) - end if - n_words = node_word_count(node_filt, "energy") - allocate(filt % energy(n_words)) - call get_node_array(node_filt, "energy", filt % energy) - - ! Allocate and store interpolant values. - if (.not. check_for_node(node_filt, "y")) then - call fatal_error("y values not specified for EnergyFunction & - &filter on tally " // trim(to_str(t % id))) - end if - n_words = node_word_count(node_filt, "y") - allocate(filt % y(n_words)) - call get_node_array(node_filt, "y", filt % y) - end select - ! Set the filter index in the tally find_filter array + type is (EnergyFunctionFilter) t % find_filter(FILTER_ENERGYFUNCTION) = j - - case default - ! Specified tally filter is invalid, raise error - call fatal_error("Unknown filter type '" & - // trim(temp_str) // "' on tally " & - // trim(to_str(t % id)) // ".") - end select - end do READ_FILTERS + ! Store the index of the filter + temp_filter(j) = i_filt + end do + + ! Store the filter indices + call move_alloc(FROM=temp_filter, TO=t % filter) ! Check that both cell and surface weren't specified if (t % find_filter(FILTER_CELL) > 0 .and. & @@ -3740,18 +3800,31 @@ contains &filter.") end if - ! Copy filters to temporary array - allocate(filters(size(t % filters) + 1)) - filters(1:size(t % filters)) = t % filters + ! Get a pointer to the mesh + i_filt = t % filter(k) + i_mesh = filters(i_filt) % obj % mesh + m => meshes(i_mesh) - ! Move allocation back -- filters becomes deallocated during + ! Copy filter indices to temporary array + allocate(temp_filter(size(t % filter) + 1)) + temp_filter(1:size(t % filter)) = t % filter + + ! Move allocation back -- temp_filter becomes deallocated during ! this call - call move_alloc(FROM=filters, TO=t%filters) + call move_alloc(FROM=temp_filter, TO=t % filter) + n_filter = size(t % filter) + + ! Copy filters to temporary array + allocate(temp_filters(size(filters) + 1)) + temp_filters(1:size(filters)) = filters + + ! Move allocation back + call move_alloc(FROM=temp_filters, TO=filters) + n_filters = size(filters) ! Add surface filter - n_filters = size(t % filters) - allocate(SurfaceFilter :: t % filters(n_filters) % obj) - select type (filt => t % filters(size(t % filters)) % obj) + allocate(SurfaceFilter::filters(n_filters) % obj) + select type (filt => filters(n_filters) % obj) type is (SurfaceFilter) filt % n_bins = 4 * m % n_dimension allocate(filt % surfaces(4 * m % n_dimension)) @@ -3766,7 +3839,7 @@ contains IN_FRONT, IN_BOTTOM, IN_TOP /) end if end select - t % find_filter(FILTER_SURFACE) = size(t % filters) + t % find_filter(FILTER_SURFACE) = n_filter case ('events') t % score_bins(j) = SCORE_EVENTS diff --git a/src/tally_filter_header.F90 b/src/tally_filter_header.F90 index 8541cd334..d934f63ff 100644 --- a/src/tally_filter_header.F90 +++ b/src/tally_filter_header.F90 @@ -14,6 +14,7 @@ module tally_filter_header !=============================================================================== type, abstract :: TallyFilter + integer :: id integer :: n_bins = 0 contains procedure(get_next_bin_), deferred :: get_next_bin diff --git a/src/tally_header.F90 b/src/tally_header.F90 index 1d34779ae..dba392279 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -37,7 +37,7 @@ module tally_header integer :: type ! volume, surface current integer :: estimator ! collision, track-length real(8) :: volume ! volume of region - type(TallyFilterContainer), allocatable :: filters(:) + integer, allocatable :: filter(:) ! index in filters array ! The stride attribute is used for determining the index in the results ! array for a matching_bin combination. Since multiple dimensions are @@ -46,9 +46,9 @@ module tally_header integer, allocatable :: stride(:) - ! This array provides a way to lookup what index in the filters array a + ! This array provides a way to lookup what index in the filter array a ! certain filter is. For example, if find_filter(FILTER_CELL) > 0, then the - ! value is the index in filters(:). + ! value is the index in filter(:). integer :: find_filter(N_FILTER_TYPES) = 0 From d5201c39f79e8a8ec25413f03bf9944fb9d8b1d9 Mon Sep 17 00:00:00 2001 From: amandalund Date: Tue, 21 Mar 2017 10:03:34 -0600 Subject: [PATCH 02/18] Separate CMFD filters --- src/cmfd_input.F90 | 205 ++++++++++++++++++++++++++------------- src/global.F90 | 2 +- src/input_xml.F90 | 73 +++++++------- src/tally_header.F90 | 4 +- src/tally_initialize.F90 | 14 +-- 5 files changed, 181 insertions(+), 117 deletions(-) diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index 1518d710f..906ec0f33 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -259,16 +259,17 @@ contains type(XMLNode), intent(in) :: root ! XML root element + logical :: energy_filters integer :: i, j ! loop counter integer :: n ! size of arrays in mesh specification integer :: ng ! number of energy groups (default 1) - integer :: n_filters ! number of filters - integer :: i_filter_mesh ! index for mesh filter + integer :: n_filter ! number of filters + integer :: i_filt ! index in filters array integer :: iarray3(3) ! temp integer array real(8) :: rarray3(3) ! temp double array - type(TallyObject), pointer :: t + type(TallyObject), pointer :: t type(RegularMesh), pointer :: m - type(TallyFilterContainer) :: filters(N_FILTER_TYPES) ! temporary filters + type(TallyFilterContainer), allocatable :: temp_filters(:) ! temporary filters type(XMLNode) :: node_mesh ! Set global variables if they are 0 (this can happen if there is no tally @@ -376,6 +377,103 @@ contains ! Add mesh to dictionary call mesh_dict % add_key(m % id, n_user_meshes + 1) + ! Determine number of filters + energy_filters = check_for_node(node_mesh, "energy") + if (energy_filters) then + n_cmfd_filters = 4 + else + n_cmfd_filters = 2 + end if + + ! Create or extend filters array + if (n_filters == 0) then + ! Allocate filters array + allocate(filters(n_cmfd_filters)) + else + ! Move filters to temporary array + allocate(temp_filters(n_filters + n_cmfd_filters)) + do i = 1, n_filters + call move_alloc(filters(i) % obj, temp_filters(i) % obj) + end do + + ! Allocate filters array with increased size + deallocate(filters) + allocate(filters(size(temp_filters)) + + ! Move allocation from temporary array to filters array + do i = 1, n_filters + call move_alloc(temp_filters(i) % obj, filters(i) % obj) + end do + + ! Deallocate temporary array + deallocate(temp_filters) + end if + + ! Set n_filters + n_filters = size(filters) + + ! Set up mesh filter + i_filt = n_user_filters + 1 + allocate(MeshFilter :: filters(i_filt) % obj) + select type (filt => filters(i_filt) % obj) + type is (MeshFilter) + filt % id = i_filt + filt % n_bins = product(m % dimension) + filt % mesh = n_user_meshes + 1 + ! Add filter to dictionary + call filter_dict % add_key(filt % id, i_filt) + end select + + if (energy_filters) then + ! Read and set incoming energy mesh filter + i_filt = i_filt + 1 + allocate(EnergyFilter :: filters(i_filt) % obj) + select type (filt => filters(i_filt) % obj) + type is (EnergyFilter) + filt % id = i_filt + ng = node_word_count(node_mesh, "energy") + filt % n_bins = ng - 1 + allocate(filt % bins(ng)) + call get_node_array(node_mesh, "energy", filt % bins) + ! Add filter to dictionary + call filter_dict % add_key(filt % id, i_filt) + end select + + ! Read and set outgoing energy mesh filter + i_filt = i_filt + 1 + allocate(EnergyoutFilter :: filters(i_filt) % obj) + select type (filt => filters(i_filt) % obj) + type is (EnergyoutFilter) + filt % id = i_filt + ng = node_word_count(node_mesh, "energy") + filt % n_bins = ng - 1 + allocate(filt % bins(ng)) + call get_node_array(node_mesh, "energy", filt % bins) + ! Add filter to dictionary + call filter_dict % add_key(filt % id, i_filt) + end select + end if + + ! Set up surface filter + i_filt = i_filt + 1 + allocate(SurfaceFilter :: filters(i_filt) % obj) + select type(filt => filters(i_filt) % obj) + type is(SurfaceFilter) + filt % id = i_filt + filt % n_bins = 4 * m % n_dimension + allocate(filt % surfaces(4 * m % n_dimension)) + if (m % n_dimension == 2) then + filt % surfaces = (/ OUT_LEFT, IN_LEFT, IN_RIGHT, OUT_RIGHT, & + OUT_BACK, IN_BACK, IN_FRONT, OUT_FRONT /) + elseif (m % n_dimension == 3) then + filt % surfaces = (/ OUT_LEFT, IN_LEFT, IN_RIGHT, OUT_RIGHT, & + OUT_BACK, IN_BACK, IN_FRONT, OUT_FRONT, & + OUT_BOTTOM, IN_BOTTOM, IN_TOP, OUT_TOP /) + end if + ! Add filter to dictionary + call filter_dict % add_key(filt % id, i_filt) + end select + ! Allocate tallies call add_tallies("cmfd", n_cmfd_tallies) @@ -390,28 +488,15 @@ contains call get_node_value(root, "reset", t % reset) end if - ! Set up mesh filter - n_filters = 1 - allocate(MeshFilter :: filters(n_filters) % obj) - select type (filt => filters(n_filters) % obj) - type is (MeshFilter) - filt % n_bins = product(m % dimension) - filt % mesh = n_user_meshes + 1 - end select - t % find_filter(FILTER_MESH) = n_filters + ! Set the mesh filter index in the tally find_filter array + n_filter = 1 + t % find_filter(FILTER_MESH) = n_user_filters + n_filter - ! Read and set incoming energy mesh filter - if (check_for_node(node_mesh, "energy")) then - n_filters = n_filters + 1 - allocate(EnergyFilter :: filters(n_filters) % obj) - select type (filt => filters(n_filters) % obj) - type is (EnergyFilter) - ng = node_word_count(node_mesh, "energy") - filt % n_bins = ng - 1 - allocate(filt % bins(ng)) - call get_node_array(node_mesh, "energy", filt % bins) - end select - t % find_filter(FILTER_ENERGYIN) = n_filters + ! Set the incoming energy mesh filter index in the tally find_filter + ! array + if (energy_filters) then + n_filter = n_filter + 1 + t % find_filter(FILTER_ENERGYIN) = n_user_filters + n_filter end if ! Set number of nucilde bins @@ -434,10 +519,11 @@ contains t % type = TALLY_VOLUME ! Allocate and set filters - allocate(t % filters(n_filters)) - do j = 1, n_filters - call move_alloc(filters(j) % obj, t % filters(j) % obj) - end do + allocate(t % filter(n_filter)) + t % filter(1) = t % find_filter(FILTER_MESH) + if (energy_filters) then + t % filter(2) = t % find_filter(FILTER_ENERGYIN) + end if ! Allocate scoring bins allocate(t % score_bins(3)) @@ -465,25 +551,20 @@ contains ! Set tally type to volume t % type = TALLY_VOLUME - ! read and set outgoing energy mesh filter - if (check_for_node(node_mesh, "energy")) then - n_filters = n_filters + 1 - allocate(EnergyoutFilter :: filters(n_filters) % obj) - select type (filt => filters(n_filters) % obj) - type is (EnergyoutFilter) - ng = node_word_count(node_mesh, "energy") - filt % n_bins = ng - 1 - allocate(filt % bins(ng)) - call get_node_array(node_mesh, "energy", filt % bins) - end select - t % find_filter(FILTER_ENERGYOUT) = n_filters + ! Set the incoming energy mesh filter index in the tally find_filter + ! array + if (energy_filters) then + n_filter = n_filter + 1 + t % find_filter(FILTER_ENERGYOUT) = n_user_filters + n_filter end if ! Allocate and set filters - allocate(t % filters(n_filters)) - do j = 1, n_filters - call move_alloc(filters(j) % obj, t % filters(j) % obj) - end do + allocate(t % filter(n_filter)) + t % filter(1) = t % find_filter(FILTER_MESH) + if (energy_filters) then + t % filter(2) = t % find_filter(FILTER_ENERGYIN) + t % filter(3) = t % find_filter(FILTER_ENERGYOUT) + end if ! Allocate macro reactions allocate(t % score_bins(2)) @@ -506,29 +587,17 @@ contains ! Set tally estimator to analog t % estimator = ESTIMATOR_ANALOG - ! Add extra filter for surface - n_filters = n_filters + 1 - allocate(SurfaceFilter :: filters(n_filters) % obj) - select type(filt => filters(n_filters) % obj) - type is(SurfaceFilter) - filt % n_bins = 4 * m % n_dimension - allocate(filt % surfaces(4 * m % n_dimension)) - if (m % n_dimension == 2) then - filt % surfaces = (/ OUT_LEFT, IN_LEFT, IN_RIGHT, OUT_RIGHT, & - OUT_BACK, IN_BACK, IN_FRONT, OUT_FRONT /) - elseif (m % n_dimension == 3) then - filt % surfaces = (/ OUT_LEFT, IN_LEFT, IN_RIGHT, OUT_RIGHT, & - OUT_BACK, IN_BACK, IN_FRONT, OUT_FRONT, & - OUT_BOTTOM, IN_BOTTOM, IN_TOP, OUT_TOP /) - end if - end select - t % find_filter(FILTER_SURFACE) = n_filters + ! Set the surface filter index in the tally find_filter array + n_filter = n_filter + 1 + t % find_filter(FILTER_SURFACE) = n_user_filters + n_cmfd_filters ! Allocate and set filters - allocate(t % filters(n_filters)) - do j = 1, n_filters - call move_alloc(filters(j) % obj, t % filters(j) % obj) - end do + allocate(t % filter(n_filter)) + t % filter(1) = t % find_filter(FILTER_MESH) + t % filter(n_filter) = t % find_filter(FILTER_SURFACE) + if (energy_filters) then + t % filter(2) = t % find_filter(FILTER_ENERGYIN) + end if ! Allocate macro reactions allocate(t % score_bins(1)) @@ -545,8 +614,8 @@ contains ! We need to increase the dimension by one since we also need ! currents coming into and out of the boundary mesh cells. - i_filter_mesh = t % find_filter(FILTER_MESH) - t % filters(i_filter_mesh) % obj % n_bins = product(m % dimension + 1) + i_filt = t % find_filter(FILTER_MESH) + filters(i_filt) % obj % n_bins = product(m % dimension + 1) end if diff --git a/src/global.F90 b/src/global.F90 index 027cf1b15..551a3b4f2 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -378,7 +378,7 @@ module global ! User-defined tally information integer :: n_cmfd_meshes = 1 ! # of structured meshes - integer :: n_cmfd_filters = 1 ! # of filters + integer :: n_cmfd_filters = 0 ! # of filters integer :: n_cmfd_tallies = 3 ! # of user-defined tallies ! Adjoint method type diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 2f1ab2a55..6f17d0ead 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2708,14 +2708,10 @@ contains ! Check for user filters n_user_filters = size(node_filt_list) - if (cmfd_run) then - n_filters = n_user_filters + n_cmfd_filters - else - n_filters = n_user_filters - end if + n_filters = n_user_filters ! Allocate filters array - if (n_user_filters > 0) allocate(filters(n_filters)) + if (n_filters > 0) allocate(filters(n_filters)) ! Check for user tallies n_user_tallies = size(node_tal_list) @@ -2998,7 +2994,7 @@ contains case ('distribcell') ! Allocate and declare the filter type - allocate(DistribcellFilter::f % obj) + allocate(DistribcellFilter :: f % obj) select type (filt => f % obj) type is (DistribcellFilter) if (n_words /= 1) call fatal_error("Only one cell can be & @@ -3009,7 +3005,7 @@ contains case ('cell') ! Allocate and declare the filter type - allocate(CellFilter::f % obj) + allocate(CellFilter :: f % obj) select type (filt => f % obj) type is (CellFilter) ! Allocate and store bins @@ -3020,7 +3016,7 @@ contains case ('cellborn') ! Allocate and declare the filter type - allocate(CellbornFilter::f % obj) + allocate(CellbornFilter :: f % obj) select type (filt => f % obj) type is (CellbornFilter) ! Allocate and store bins @@ -3031,7 +3027,7 @@ contains case ('material') ! Allocate and declare the filter type - allocate(MaterialFilter::f % obj) + allocate(MaterialFilter :: f % obj) select type (filt => f % obj) type is (MaterialFilter) ! Allocate and store bins @@ -3042,7 +3038,7 @@ contains case ('universe') ! Allocate and declare the filter type - allocate(UniverseFilter::f % obj) + allocate(UniverseFilter :: f % obj) select type (filt => f % obj) type is (UniverseFilter) ! Allocate and store bins @@ -3054,7 +3050,7 @@ contains case ('surface') call fatal_error("Surface filter is not yet supported!") ! Allocate and declare the filter type - allocate(SurfaceFilter::f % obj) + allocate(SurfaceFilter :: f % obj) select type (filt => f % obj) type is (SurfaceFilter) ! Allocate and store bins @@ -3065,7 +3061,7 @@ contains case ('mesh') ! Allocate and declare the filter type - allocate(MeshFilter::f % obj) + allocate(MeshFilter :: f % obj) select type (filt => f % obj) type is (MeshFilter) if (n_words /= 1) call fatal_error("Only one mesh can be & @@ -3093,7 +3089,7 @@ contains case ('energy') ! Allocate and declare the filter type - allocate(EnergyFilter::f % obj) + allocate(EnergyFilter :: f % obj) select type (filt => f % obj) type is (EnergyFilter) ! Allocate and store bins @@ -3117,7 +3113,7 @@ contains case ('energyout') ! Allocate and declare the filter type - allocate(EnergyoutFilter::f % obj) + allocate(EnergyoutFilter :: f % obj) select type (filt => f % obj) type is (EnergyoutFilter) ! Allocate and store bins @@ -3142,7 +3138,7 @@ contains case ('delayedgroup') ! Allocate and declare the filter type - allocate(DelayedGroupFilter::f % obj) + allocate(DelayedGroupFilter :: f % obj) select type (filt => f % obj) type is (DelayedGroupFilter) ! Allocate and store bins @@ -3164,7 +3160,7 @@ contains case ('mu') ! Allocate and declare the filter type - allocate(MuFilter::f % obj) + allocate(MuFilter :: f % obj) select type (filt => f % obj) type is (MuFilter) ! Allocate and store bins @@ -3195,7 +3191,7 @@ contains case ('polar') ! Allocate and declare the filter type - allocate(PolarFilter::f % obj) + allocate(PolarFilter :: f % obj) select type (filt => f % obj) type is (PolarFilter) ! Allocate and store bins @@ -3226,7 +3222,7 @@ contains case ('azimuthal') ! Allocate and declare the filter type - allocate(AzimuthalFilter::f % obj) + allocate(AzimuthalFilter :: f % obj) select type (filt => f % obj) type is (AzimuthalFilter) ! Allocate and store bins @@ -3258,7 +3254,7 @@ contains case ('energyfunction') ! Allocate and declare the filter type. - allocate(EnergyFunctionFilter::f % obj) + allocate(EnergyFunctionFilter :: f % obj) select type (filt => f % obj) type is (EnergyFunctionFilter) filt % n_bins = 1 @@ -3366,37 +3362,37 @@ contains ! Set the filter index in the tally find_filter array select type (f % obj) type is (DistribcellFilter) - t % find_filter(FILTER_DISTRIBCELL) = j + t % find_filter(FILTER_DISTRIBCELL) = i_filt type is (CellFilter) - t % find_filter(FILTER_CELL) = j + t % find_filter(FILTER_CELL) = i_filt type is (CellbornFilter) - t % find_filter(FILTER_CELLBORN) = j + t % find_filter(FILTER_CELLBORN) = i_filt type is (MaterialFilter) - t % find_filter(FILTER_MATERIAL) = j + t % find_filter(FILTER_MATERIAL) = i_filt type is (UniverseFilter) - t % find_filter(FILTER_UNIVERSE) = j + t % find_filter(FILTER_UNIVERSE) = i_filt type is (SurfaceFilter) - t % find_filter(FILTER_SURFACE) = j + t % find_filter(FILTER_SURFACE) = i_filt type is (MeshFilter) - t % find_filter(FILTER_MESH) = j + t % find_filter(FILTER_MESH) = i_filt type is (EnergyFilter) - t % find_filter(FILTER_ENERGYIN) = j + t % find_filter(FILTER_ENERGYIN) = i_filt type is (EnergyoutFilter) - t % find_filter(FILTER_ENERGYOUT) = j + t % find_filter(FILTER_ENERGYOUT) = i_filt ! Set to analog estimator t % estimator = ESTIMATOR_ANALOG type is (DelayedGroupFilter) - t % find_filter(FILTER_DELAYEDGROUP) = j + t % find_filter(FILTER_DELAYEDGROUP) = i_filt type is (MuFilter) - t % find_filter(FILTER_MU) = j + t % find_filter(FILTER_MU) = i_filt ! Set to analog estimator t % estimator = ESTIMATOR_ANALOG type is (PolarFilter) - t % find_filter(FILTER_POLAR) = j + t % find_filter(FILTER_POLAR) = i_filt type is (AzimuthalFilter) - t % find_filter(FILTER_AZIMUTHAL) = j + t % find_filter(FILTER_AZIMUTHAL) = i_filt type is (EnergyFunctionFilter) - t % find_filter(FILTER_ENERGYFUNCTION) = j + t % find_filter(FILTER_ENERGYFUNCTION) = i_filt end select ! Store the index of the filter @@ -3792,16 +3788,15 @@ contains end if ! Get index of mesh filter - k = t % find_filter(FILTER_MESH) + i_filt = t % find_filter(FILTER_MESH) ! Check to make sure mesh filter was specified - if (k == 0) then + if (i_filt == 0) then call fatal_error("Cannot tally surface current without a mesh & &filter.") end if ! Get a pointer to the mesh - i_filt = t % filter(k) i_mesh = filters(i_filt) % obj % mesh m => meshes(i_mesh) @@ -3823,7 +3818,7 @@ contains n_filters = size(filters) ! Add surface filter - allocate(SurfaceFilter::filters(n_filters) % obj) + allocate(SurfaceFilter :: filters(n_filters) % obj) select type (filt => filters(n_filters) % obj) type is (SurfaceFilter) filt % n_bins = 4 * m % n_dimension @@ -3839,7 +3834,7 @@ contains IN_FRONT, IN_BOTTOM, IN_TOP /) end if end select - t % find_filter(FILTER_SURFACE) = n_filter + t % find_filter(FILTER_SURFACE) = n_filters case ('events') t % score_bins(j) = SCORE_EVENTS diff --git a/src/tally_header.F90 b/src/tally_header.F90 index dba392279..76e3d143f 100644 --- a/src/tally_header.F90 +++ b/src/tally_header.F90 @@ -46,9 +46,9 @@ module tally_header integer, allocatable :: stride(:) - ! This array provides a way to lookup what index in the filter array a + ! This array provides a way to lookup what index in the filters array a ! certain filter is. For example, if find_filter(FILTER_CELL) > 0, then the - ! value is the index in filter(:). + ! value is the index in filters(:). integer :: find_filter(N_FILTER_TYPES) = 0 diff --git a/src/tally_initialize.F90 b/src/tally_initialize.F90 index 0e7a50a9c..4416af8bb 100644 --- a/src/tally_initialize.F90 +++ b/src/tally_initialize.F90 @@ -37,7 +37,7 @@ contains integer :: i ! loop index for tallies integer :: j ! loop index for filters integer :: n ! temporary stride - integer :: max_n_filters = 0 ! maximum number of filters + integer :: i_filt ! filter index type(TallyObject), pointer :: t TALLY_LOOP: do i = 1, n_tallies @@ -45,17 +45,17 @@ contains t => tallies(i) ! Allocate stride and matching_bins arrays - allocate(t % stride(size(t % filters))) - max_n_filters = max(max_n_filters, size(t % filters)) + allocate(t % stride(size(t % filter))) ! The filters are traversed in opposite order so that the last filter has ! the shortest stride in memory and the first filter has the largest ! stride n = 1 - STRIDE: do j = size(t % filters), 1, -1 + STRIDE: do j = size(t % filter), 1, -1 + i_filt = t % filter(j) t % stride(j) = n - n = n * t % filters(j) % obj % n_bins + n = n * filters(i_filt) % obj % n_bins end do STRIDE ! Set total number of filter and scoring bins @@ -70,8 +70,8 @@ contains ! Allocate array for matching filter bins !$omp parallel - allocate(matching_bins(max_n_filters)) - allocate(filter_weights(max_n_filters)) + allocate(matching_bins(n_filters)) + allocate(filter_weights(n_filters)) !$omp end parallel end subroutine setup_tally_arrays From ed4d2a034bfb0a3b455428897081cf4fcb3948cb Mon Sep 17 00:00:00 2001 From: amandalund Date: Wed, 22 Mar 2017 20:57:33 -0500 Subject: [PATCH 03/18] Fix CMFD; fix input XML; method to extend filters array --- src/cmfd_data.F90 | 45 +++++++++++++++------------- src/cmfd_input.F90 | 56 ++++++++++------------------------ src/input_xml.F90 | 65 +++++++++++++++++++++------------------- src/tally_filter.F90 | 39 ++++++++++++++++++++++++ src/tally_initialize.F90 | 6 ++-- 5 files changed, 118 insertions(+), 93 deletions(-) diff --git a/src/cmfd_data.F90 b/src/cmfd_data.F90 index 29e164440..a2a642fc7 100644 --- a/src/cmfd_data.F90 +++ b/src/cmfd_data.F90 @@ -56,8 +56,8 @@ contains IN_BACK, IN_FRONT, IN_BOTTOM, IN_TOP, CMFD_NOACCEL, & ZERO, ONE, TINY_BIT use error, only: fatal_error - use global, only: cmfd, n_cmfd_tallies, cmfd_tallies, meshes,& - matching_bins + use global, only: cmfd, n_cmfd_tallies, cmfd_tallies, meshes, & + filters, matching_bins use mesh, only: mesh_indices_to_bin use mesh_header, only: RegularMesh use string, only: to_str @@ -76,6 +76,7 @@ contains integer :: ijk(3) ! indices for mesh cell integer :: score_index ! index to pull from tally object integer :: i_mesh ! index in meshes array + integer :: i_filt ! index in filters array integer :: i_filter_mesh ! index for mesh filter integer :: i_filter_ein ! index for incoming energy filter integer :: i_filter_eout ! index for outgoing energy filter @@ -96,7 +97,8 @@ contains ! Associate tallies and mesh t => cmfd_tallies(1) - select type(filt => t % filters(t % find_filter(FILTER_MESH)) % obj) + i_filt = t % filter(t % find_filter(FILTER_MESH)) + select type(filt => filters(i_filt) % obj) type is (MeshFilter) i_mesh = filt % mesh end select @@ -114,7 +116,8 @@ contains ! Associate tallies and mesh t => cmfd_tallies(ital) - select type(filt => t % filters(t % find_filter(FILTER_MESH)) % obj) + i_filt = t % filter(t % find_filter(FILTER_MESH)) + select type(filt => filters(i_filt) % obj) type is (MeshFilter) i_mesh = filt % mesh end select @@ -146,7 +149,7 @@ contains TALLY: if (ital == 1) then ! Reset all bins to 1 - matching_bins(1:size(t % filters)) = 1 + matching_bins(1:size(t % filter)) = 1 ! Set ijk as mesh indices ijk = (/ i, j, k /) @@ -160,7 +163,7 @@ contains end if ! Calculate score index from bins - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t%stride) + 1 ! Get flux @@ -190,7 +193,7 @@ contains INGROUP: do g = 1, ng ! Reset all bins to 1 - matching_bins(1:size(t % filters)) = 1 + matching_bins(1:size(t % filter)) = 1 ! Set ijk as mesh indices ijk = (/ i, j, k /) @@ -207,7 +210,7 @@ contains end if ! Calculate score index from bins - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t%stride) + 1 ! Get scattering @@ -229,7 +232,7 @@ contains else if (ital == 3) then ! Initialize and filter for energy - matching_bins(1:size(t % filters)) = 1 + matching_bins(1:size(t % filter)) = 1 if (i_filter_ein > 0) then matching_bins(i_filter_ein) = ng - h + 1 end if @@ -240,67 +243,67 @@ contains ! Left surface matching_bins(i_filter_surf) = OUT_LEFT - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(1,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = IN_LEFT - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(2,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Right surface matching_bins(i_filter_surf) = IN_RIGHT - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(3,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = OUT_RIGHT - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(4,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Back surface matching_bins(i_filter_surf) = OUT_BACK - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(5,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = IN_BACK - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(6,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Front surface matching_bins(i_filter_surf) = IN_FRONT - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(7,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = OUT_FRONT - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(8,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Bottom surface matching_bins(i_filter_surf) = OUT_BOTTOM - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(9,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = IN_BOTTOM - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(10,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Top surface matching_bins(i_filter_surf) = IN_TOP - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(11,h,i,j,k) = t % results(RESULT_SUM,1,score_index) matching_bins(i_filter_surf) = OUT_TOP - score_index = sum((matching_bins(1:size(t % filters)) - 1) & + score_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 cmfd % current(12,h,i,j,k) = t % results(RESULT_SUM,1,score_index) diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index 906ec0f33..1fc15e845 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -385,32 +385,8 @@ contains n_cmfd_filters = 2 end if - ! Create or extend filters array - if (n_filters == 0) then - ! Allocate filters array - allocate(filters(n_cmfd_filters)) - else - ! Move filters to temporary array - allocate(temp_filters(n_filters + n_cmfd_filters)) - do i = 1, n_filters - call move_alloc(filters(i) % obj, temp_filters(i) % obj) - end do - - ! Allocate filters array with increased size - deallocate(filters) - allocate(filters(size(temp_filters)) - - ! Move allocation from temporary array to filters array - do i = 1, n_filters - call move_alloc(temp_filters(i) % obj, filters(i) % obj) - end do - - ! Deallocate temporary array - deallocate(temp_filters) - end if - - ! Set n_filters - n_filters = size(filters) + ! Extend filters array so we can add CMFD filters + call add_filters(n_cmfd_filters) ! Set up mesh filter i_filt = n_user_filters + 1 @@ -490,13 +466,13 @@ contains ! Set the mesh filter index in the tally find_filter array n_filter = 1 - t % find_filter(FILTER_MESH) = n_user_filters + n_filter + t % find_filter(FILTER_MESH) = n_filter ! Set the incoming energy mesh filter index in the tally find_filter ! array if (energy_filters) then n_filter = n_filter + 1 - t % find_filter(FILTER_ENERGYIN) = n_user_filters + n_filter + t % find_filter(FILTER_ENERGYIN) = n_filter end if ! Set number of nucilde bins @@ -520,9 +496,9 @@ contains ! Allocate and set filters allocate(t % filter(n_filter)) - t % filter(1) = t % find_filter(FILTER_MESH) + t % filter(1) = n_user_filters + 1 if (energy_filters) then - t % filter(2) = t % find_filter(FILTER_ENERGYIN) + t % filter(2) = n_user_filters + 2 end if ! Allocate scoring bins @@ -555,15 +531,15 @@ contains ! array if (energy_filters) then n_filter = n_filter + 1 - t % find_filter(FILTER_ENERGYOUT) = n_user_filters + n_filter + t % find_filter(FILTER_ENERGYOUT) = n_filter end if - ! Allocate and set filters + ! Allocate and set indices in filters array allocate(t % filter(n_filter)) - t % filter(1) = t % find_filter(FILTER_MESH) + t % filter(1) = n_user_filters + 1 if (energy_filters) then - t % filter(2) = t % find_filter(FILTER_ENERGYIN) - t % filter(3) = t % find_filter(FILTER_ENERGYOUT) + t % filter(2) = n_user_filters + 2 + t % filter(3) = n_user_filters + 3 end if ! Allocate macro reactions @@ -589,14 +565,14 @@ contains ! Set the surface filter index in the tally find_filter array n_filter = n_filter + 1 - t % find_filter(FILTER_SURFACE) = n_user_filters + n_cmfd_filters + t % find_filter(FILTER_SURFACE) = n_cmfd_filters ! Allocate and set filters allocate(t % filter(n_filter)) - t % filter(1) = t % find_filter(FILTER_MESH) - t % filter(n_filter) = t % find_filter(FILTER_SURFACE) + t % filter(1) = n_user_filters + 1 + t % filter(n_filter) = n_user_filters + n_cmfd_filters if (energy_filters) then - t % filter(2) = t % find_filter(FILTER_ENERGYIN) + t % filter(2) = n_user_filters + 2 end if ! Allocate macro reactions @@ -614,7 +590,7 @@ contains ! We need to increase the dimension by one since we also need ! currents coming into and out of the boundary mesh cells. - i_filt = t % find_filter(FILTER_MESH) + i_filt = t % filter(t % find_filter(FILTER_MESH)) filters(i_filt) % obj % n_bins = product(m % dimension + 1) end if diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 6f17d0ead..e6aeae324 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2646,7 +2646,6 @@ contains type(TallyObject), pointer :: t type(TallyFilterContainer), pointer :: f type(RegularMesh), pointer :: m - type(TallyFilterContainer), allocatable :: temp_filters(:) type(XMLDocument) :: doc type(XMLNode) :: root type(XMLNode) :: node_mesh @@ -2708,10 +2707,9 @@ contains ! Check for user filters n_user_filters = size(node_filt_list) - n_filters = n_user_filters ! Allocate filters array - if (n_filters > 0) allocate(filters(n_filters)) + if (n_user_filters > 0) call add_filters(n_user_filters) ! Check for user tallies n_user_tallies = size(node_tal_list) @@ -3362,37 +3360,37 @@ contains ! Set the filter index in the tally find_filter array select type (f % obj) type is (DistribcellFilter) - t % find_filter(FILTER_DISTRIBCELL) = i_filt + t % find_filter(FILTER_DISTRIBCELL) = j type is (CellFilter) - t % find_filter(FILTER_CELL) = i_filt + t % find_filter(FILTER_CELL) = j type is (CellbornFilter) - t % find_filter(FILTER_CELLBORN) = i_filt + t % find_filter(FILTER_CELLBORN) = j type is (MaterialFilter) - t % find_filter(FILTER_MATERIAL) = i_filt + t % find_filter(FILTER_MATERIAL) = j type is (UniverseFilter) - t % find_filter(FILTER_UNIVERSE) = i_filt + t % find_filter(FILTER_UNIVERSE) = j type is (SurfaceFilter) - t % find_filter(FILTER_SURFACE) = i_filt + t % find_filter(FILTER_SURFACE) = j type is (MeshFilter) - t % find_filter(FILTER_MESH) = i_filt + t % find_filter(FILTER_MESH) = j type is (EnergyFilter) - t % find_filter(FILTER_ENERGYIN) = i_filt + t % find_filter(FILTER_ENERGYIN) = j type is (EnergyoutFilter) - t % find_filter(FILTER_ENERGYOUT) = i_filt + t % find_filter(FILTER_ENERGYOUT) = j ! Set to analog estimator t % estimator = ESTIMATOR_ANALOG type is (DelayedGroupFilter) - t % find_filter(FILTER_DELAYEDGROUP) = i_filt + t % find_filter(FILTER_DELAYEDGROUP) = j type is (MuFilter) - t % find_filter(FILTER_MU) = i_filt + t % find_filter(FILTER_MU) = j ! Set to analog estimator t % estimator = ESTIMATOR_ANALOG type is (PolarFilter) - t % find_filter(FILTER_POLAR) = i_filt + t % find_filter(FILTER_POLAR) = j type is (AzimuthalFilter) - t % find_filter(FILTER_AZIMUTHAL) = i_filt + t % find_filter(FILTER_AZIMUTHAL) = j type is (EnergyFunctionFilter) - t % find_filter(FILTER_ENERGYFUNCTION) = i_filt + t % find_filter(FILTER_ENERGYFUNCTION) = j end select ! Store the index of the filter @@ -3788,7 +3786,7 @@ contains end if ! Get index of mesh filter - i_filt = t % find_filter(FILTER_MESH) + i_filt = t % filter(t % find_filter(FILTER_MESH)) ! Check to make sure mesh filter was specified if (i_filt == 0) then @@ -3796,9 +3794,18 @@ contains &filter.") end if - ! Get a pointer to the mesh - i_mesh = filters(i_filt) % obj % mesh - m => meshes(i_mesh) + ! Declare the type of the mesh filter + select type(filt => filters(i_filt) % obj) + type is (MeshFilter) + + ! Get pointer to mesh + i_mesh = filt % mesh + m => meshes(i_mesh) + + ! We need to increase the dimension by one since we also need + ! currents coming into and out of the boundary mesh cells. + filt % n_bins = product(m % dimension + 1) + end select ! Copy filter indices to temporary array allocate(temp_filter(size(t % filter) + 1)) @@ -3809,13 +3816,11 @@ contains call move_alloc(FROM=temp_filter, TO=t % filter) n_filter = size(t % filter) - ! Copy filters to temporary array - allocate(temp_filters(size(filters) + 1)) - temp_filters(1:size(filters)) = filters + ! Extend the filters array so we can add a surface filter + call add_filters(1) - ! Move allocation back - call move_alloc(FROM=temp_filters, TO=filters) - n_filters = size(filters) + ! Increment number of user filters + n_user_filters = n_user_filters + 1 ! Add surface filter allocate(SurfaceFilter :: filters(n_filters) % obj) @@ -3834,7 +3839,7 @@ contains IN_FRONT, IN_BOTTOM, IN_TOP /) end if end select - t % find_filter(FILTER_SURFACE) = n_filters + t % find_filter(FILTER_SURFACE) = n_filter case ('events') t % score_bins(j) = SCORE_EVENTS @@ -4588,8 +4593,8 @@ contains &meshlines on plot " // trim(to_str(pl % id))) end if - select type(filt => cmfd_tallies(1) % & - filters(cmfd_tallies(1) % find_filter(FILTER_MESH)) % obj) + select type(filt => filters(cmfd_tallies(1) % & + filter(cmfd_tallies(1) % find_filter(FILTER_MESH))) % obj) type is (MeshFilter) i_mesh = filt % mesh end select diff --git a/src/tally_filter.F90 b/src/tally_filter.F90 index efa944d90..64abec87c 100644 --- a/src/tally_filter.F90 +++ b/src/tally_filter.F90 @@ -1646,4 +1646,43 @@ contains end do end subroutine find_offset +!=============================================================================== +! ADD_FILTERS creates or extends the filters array +!=============================================================================== + + subroutine add_filters(n) + + integer, intent(in) :: n ! number of filters to add + + integer :: i ! loop counter + type(TallyFilterContainer), allocatable :: temp(:) ! temporary filters + + if (n_filters == 0) then + ! Allocate filters array + allocate(filters(n)) + else + ! Move filters to temporary array + allocate(temp(n_filters + n)) + do i = 1, n_filters + call move_alloc(filters(i) % obj, temp(i) % obj) + end do + + ! Allocate filters array with increased size + deallocate(filters) + allocate(filters(size(temp)) + + ! Move filters back from temporary array to filters array + do i = 1, n_filters + call move_alloc(temp(i) % obj, filters(i) % obj) + end do + + ! Deallocate temporary array + deallocate(temp) + end if + + ! Set n_filters + n_filters = size(filters) + + end subroutine add_filters + end module tally_filter diff --git a/src/tally_initialize.F90 b/src/tally_initialize.F90 index 4416af8bb..8baabcd82 100644 --- a/src/tally_initialize.F90 +++ b/src/tally_initialize.F90 @@ -38,6 +38,7 @@ contains integer :: j ! loop index for filters integer :: n ! temporary stride integer :: i_filt ! filter index + integer :: max_n_filters = 0 ! maximum number of filters type(TallyObject), pointer :: t TALLY_LOOP: do i = 1, n_tallies @@ -46,6 +47,7 @@ contains ! Allocate stride and matching_bins arrays allocate(t % stride(size(t % filter))) + max_n_filters = max(max_n_filters, size(t % filter)) ! The filters are traversed in opposite order so that the last filter has ! the shortest stride in memory and the first filter has the largest @@ -70,8 +72,8 @@ contains ! Allocate array for matching filter bins !$omp parallel - allocate(matching_bins(n_filters)) - allocate(filter_weights(n_filters)) + allocate(matching_bins(max_n_filters)) + allocate(filter_weights(max_n_filters)) !$omp end parallel end subroutine setup_tally_arrays From f08567b096fe22c184940b09654c3299713ce56a Mon Sep 17 00:00:00 2001 From: amandalund Date: Mon, 27 Mar 2017 10:03:27 -0500 Subject: [PATCH 04/18] Changed python API; changed how filters are written to statepoint; changed tally filters array to indices of filters in global array --- docs/source/io_formats/statepoint.rst | 36 +++--- openmc/filter.py | 145 +++++++++++++++++++--- openmc/statepoint.py | 7 +- openmc/tallies.py | 18 ++- src/initialize.F90 | 16 +-- src/output.F90 | 56 +++++---- src/state_point.F90 | 39 ++++-- src/tally.F90 | 170 +++++++++++++------------- src/trigger.F90 | 22 ++-- 9 files changed, 334 insertions(+), 175 deletions(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 98cc9e4b5..af6e3a1bc 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -92,6 +92,26 @@ The current version of the statepoint file format is 16.0. - **width** (*double[]*) -- Width of each mesh cell in each dimension. +**/tallies/filters/** + +:Attributes: - **n_filters** (*int*) -- Number of filters in the problem. + - **ids** (*int[]*) -- User-defined unique ID of each filter. + +**/tallies/filters/filter /** + +:Datasets: - **type** (*char[]*) -- Type of the j-th filter. Can be 'universe', + 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy', + 'energyout', 'distribcell', 'mu', 'polar', 'azimuthal', + 'delayedgroup', or 'energyfunction'. + - **n_bins** (*int*) -- Number of bins for the j-th filter. Not + present for 'energyfunction' filters. + - **bins** (*int[]* or *double[]*) -- Value for each filter bin of + this type. Not present for 'energyfunction' filters. + - **energy** (*double[]*) -- Energy grid points for energyfunction + interpolation. Only used for 'energyfunction' filters. + - **y** (*double[]*) -- Interpolant values for energyfunction + interpolation. Only used for 'energyfunction' filters. + **/tallies/derivatives/derivative /** :Datasets: - **independent variable** (*char[]*) -- Independent variable of @@ -105,6 +125,7 @@ The current version of the statepoint file format is 16.0. :Datasets: - **n_realizations** (*int*) -- Number of realizations. - **n_filters** (*int*) -- Number of filters used. + - **filters** (*int[]*) -- IDs of the filters on the tally - **nuclides** (*char[][]*) -- Array of nuclides to tally. Note that if no nuclide is specified in the user input, a single 'total' nuclide appears here. @@ -126,21 +147,6 @@ The current version of the statepoint file format is 16.0. scoring bins, and the third dimension has two entries for the sum and the sum-of-squares. -**/tallies/tally /filter /** - -:Datasets: - **type** (*char[]*) -- Type of the j-th filter. Can be 'universe', - 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy', - 'energyout', 'distribcell', 'mu', 'polar', 'azimuthal', - 'delayedgroup', or 'energyfunction'. - - **n_bins** (*int*) -- Number of bins for the j-th filter. Not - present for 'energyfunction' filters. - - **bins** (*int[]* or *double[]*) -- Value for each filter bin of - this type. Not present for 'energyfunction' filters. - - **energy** (*double[]*) -- Energy grid points for energyfunction - interpolation. Only used for 'energyfunction' filters. - - **y** (*double[]*) -- Interpolant values for energyfunction - interpolation. Only used for 'energyfunction' filters. - **/runtime/** All values are given in seconds and are measured on the master process. diff --git a/openmc/filter.py b/openmc/filter.py index 676bc66e1..4e1b4ccb9 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -13,6 +13,9 @@ import openmc import openmc.checkvalue as cv +# "Static" variable for auto-generated Filter IDs +AUTO_FILTER_ID = 10000 + _FILTER_TYPES = ['universe', 'material', 'cell', 'cellborn', 'surface', 'mesh', 'energy', 'energyout', 'mu', 'polar', 'azimuthal', 'distribcell', 'delayedgroup', 'energyfunction'] @@ -25,6 +28,12 @@ _CURRENT_NAMES = {1: 'x-min out', 2: 'x-min in', 11: 'z-max out', 12: 'z-max in'} +def reset_auto_filter_id(): + """Reset counter for auto-generated filter IDs.""" + global AUTO_FILTER_ID + AUTO_FILTER_ID = 10000 + + class FilterMeta(ABCMeta): def __new__(cls, name, bases, namespace, **kwargs): # Check the class name. @@ -73,11 +82,15 @@ class Filter(object): The bins for the filter. This takes on different meaning for different filters. See the docstrings for sublcasses of this filter or the online documentation for more details. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Integral or Iterable of Integral or Iterable of Real The bins for the filter + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -86,8 +99,9 @@ class Filter(object): """ - def __init__(self, bins): + def __init__(self, bins, filter_id=None): self.bins = bins + self.id = filter_id self._num_bins = 0 self._stride = None @@ -125,6 +139,7 @@ class Filter(object): def __repr__(self): string = type(self).__name__ + '\n' string += '{: <16}=\t{}\n'.format('\tBins', self.bins) + string += '{: <16}=\t{}\n'.format('\tID', self.id) return string @classmethod @@ -155,10 +170,12 @@ class Filter(object): """ + filter_id = int(group.name.split('/')[-1].lstrip('filter ')) + # If the HDF5 'type' variable matches this class's short_name, then # there is no overriden from_hdf5 method. Pass the bins to __init__. if group['type'].value.decode() == cls.short_name.lower(): - out = cls(group['bins'].value) + out = cls(group['bins'].value, filter_id) out.num_bins = group['n_bins'].value return out @@ -175,6 +192,10 @@ class Filter(object): def bins(self): return self._bins + @property + def id(self): + return self._id + @property def num_bins(self): return self._num_bins @@ -193,6 +214,17 @@ class Filter(object): self._bins = bins + @id.setter + def id(self, filter_id): + if filter_id is None: + global AUTO_FILTER_ID + self._id = AUTO_FILTER_ID + AUTO_FILTER_ID += 1 + else: + cv.check_type('filter ID', filter_id, Integral) + cv.check_greater_than('filter ID', filter_id, 0, equality=True) + self._id = filter_id + @num_bins.setter def num_bins(self, num_bins): cv.check_type('filter num_bins', num_bins, Integral) @@ -226,13 +258,18 @@ class Filter(object): Returns ------- - ElementTree.Element + element : xml.etree.ElementTree.Element + XML element containing filter data """ element = ET.Element('filter') + element.set('id', str(self.id)) element.set('type', self.short_name.lower()) - element.set('bins', ' '.join(str(b) for b in self.bins)) + + subelement = ET.SubElement(element, 'bins') + subelement.text = ' '.join(str(b) for b in self.bins) + return element def can_merge(self, other): @@ -279,7 +316,7 @@ class Filter(object): merged_bins = np.concatenate((self.bins, other.bins)) merged_bins = np.unique(merged_bins) - # Create a new filter with these bins + # Create a new filter with these bins and a new auto-generated ID return type(self)(merged_bins) def is_subset(self, other): @@ -443,11 +480,15 @@ class IntegralFilter(Filter): The bins for the filter. This takes on different meaning for different filters. See the docstrings for sublcasses of this filter or the online documentation for more details. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Integral or Iterable of Integral The bins for the filter + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -478,11 +519,15 @@ class UniverseFilter(IntegralFilter): ---------- bins : Integral or Iterable of Integral openmc.Universe IDs. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Integral or Iterable of Integral openmc.Universe IDs. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -499,11 +544,15 @@ class MaterialFilter(IntegralFilter): ---------- bins : Integral or Iterable of Integral openmc.Material IDs. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Integral or Iterable of Integral openmc.Material IDs. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -520,11 +569,15 @@ class CellFilter(IntegralFilter): ---------- bins : Integral or Iterable of Integral openmc.Cell IDs. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Integral or Iterable of Integral openmc.Cell IDs. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -541,11 +594,15 @@ class CellbornFilter(IntegralFilter): ---------- bins : Integral or Iterable of Integral openmc.Cell IDs. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Integral or Iterable of Integral openmc.Cell IDs. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -563,12 +620,16 @@ class SurfaceFilter(IntegralFilter): bins : Iterable of Integral Indices corresponding to which face of a mesh cell the current is crossing. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Iterable of Integral Indices corresponding to which face of a mesh cell the current is crossing. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -630,6 +691,8 @@ class MeshFilter(Filter): ---------- mesh : openmc.Mesh The Mesh object that events will be tallied onto + filter_id : int + Unique identifier for the filter Attributes ---------- @@ -637,6 +700,8 @@ class MeshFilter(Filter): The Mesh ID mesh : openmc.Mesh The Mesh object that events will be tallied onto + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -645,9 +710,9 @@ class MeshFilter(Filter): """ - def __init__(self, mesh): + def __init__(self, mesh, filter_id=None): self.mesh = mesh - super(MeshFilter, self).__init__(mesh.id) + super(MeshFilter, self).__init__(mesh.id, filter_id) @classmethod def from_hdf5(cls, group, **kwargs): @@ -662,8 +727,9 @@ class MeshFilter(Filter): mesh_id = group['bins'].value mesh_obj = kwargs['meshes'][mesh_id] + filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - out = cls(mesh_obj) + out = cls(mesh_obj, filter_id) out.num_bins = group['n_bins'].value return out @@ -818,11 +884,15 @@ class RealFilter(Filter): ---------- bins : Iterable of Real A grid of bin values. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Iterable of Real A grid of bin values. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -872,7 +942,7 @@ class RealFilter(Filter): merged_bins = np.concatenate((self.bins, other.bins)) merged_bins = np.unique(merged_bins) - # Create a new filter with these bins + # Create a new filter with these bins and a new auto-generated ID return type(self)(sorted(merged_bins)) def is_subset(self, other): @@ -925,11 +995,15 @@ class EnergyFilter(RealFilter): ---------- bins : Iterable of Real A grid of energy values in eV. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Iterable of Real A grid of energy values in eV. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -1027,11 +1101,15 @@ class EnergyoutFilter(EnergyFilter): ---------- bins : Iterable of Real A grid of energy values in eV. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Iterable of Real A grid of energy values in eV. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -1085,11 +1163,15 @@ class DistribcellFilter(Filter): bins : Integral or Iterable of Integral or Iterable of Real The bins for the filter. This takes on different meaning for different filters. See the OpenMC online documentation for more details. + filter_id : int + Unique identifier for the filter Attributes ---------- bins : Integral or Iterable of Integral or Iterable of Real The bins for the filter + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -1101,9 +1183,9 @@ class DistribcellFilter(Filter): """ - def __init__(self, bins): + def __init__(self, bins, filter_id=None): self._paths = None - super(DistribcellFilter, self).__init__(bins) + super(DistribcellFilter, self).__init__(bins, filter_id) @classmethod def from_hdf5(cls, group, **kwargs): @@ -1112,7 +1194,9 @@ class DistribcellFilter(Filter): + cls.short_name.lower() + "' but got '" + group['type'].value.decode() + " instead") - out = cls(group['bins'].value) + filter_id = int(group.name.split('/')[-1].lstrip('filter ')) + + out = cls(group['bins'].value, filter_id) out.num_bins = group['n_bins'].value return out @@ -1310,6 +1394,8 @@ class MuFilter(RealFilter): the values will be used explicitly as grid points. If a single Integral is given, the range [-1, 1] will be divided up equally into that number of bins. + filter_id : int + Unique identifier for the filter Attributes ---------- @@ -1319,6 +1405,8 @@ class MuFilter(RealFilter): the values will be used explicitly as grid points. If a single Integral is given, the range [-1, 1] will be divided up equally into that number of bins. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -1413,6 +1501,8 @@ class PolarFilter(RealFilter): the values will be used explicitly as grid points. If a single Integral is given, the range [0, pi] will be divided up equally into that number of bins. + filter_id : int + Unique identifier for the filter Attributes ---------- @@ -1422,6 +1512,8 @@ class PolarFilter(RealFilter): the values will be used explicitly as grid points. If a single Integral is given, the range [0, pi] will be divided up equally into that number of bins. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -1516,6 +1608,8 @@ class AzimuthalFilter(RealFilter): to the z-axis. If an Iterable is given, the values will be used explicitly as grid points. If a single Integral is given, the range [-pi, pi) will be divided up equally into that number of bins. + filter_id : int + Unique identifier for the filter Attributes ---------- @@ -1525,6 +1619,8 @@ class AzimuthalFilter(RealFilter): to the z-axis. If an Iterable is given, the values will be used explicitly as grid points. If a single Integral is given, the range [-pi, pi) will be divided up equally into that number of bins. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -1617,6 +1713,8 @@ class DelayedGroupFilter(IntegralFilter): The delayed neutron precursor groups. For example, ENDF/B-VII.1 uses 6 precursor groups so a tally with all groups will have bins = [1, 2, 3, 4, 5, 6]. + filter_id : int + Unique identifier for the filter Attributes ---------- @@ -1624,6 +1722,8 @@ class DelayedGroupFilter(IntegralFilter): The delayed neutron precursor groups. For example, ENDF/B-VII.1 uses 6 precursor groups so a tally with all groups will have bins = [1, 2, 3, 4, 5, 6]. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins stride : Integral @@ -1646,6 +1746,8 @@ class EnergyFunctionFilter(Filter): A grid of energy values in eV. y : iterable of Real A grid of interpolant values in eV. + filter_id : int + Unique identifier for the filter Attributes ---------- @@ -1653,6 +1755,8 @@ class EnergyFunctionFilter(Filter): A grid of energy values in eV. y : iterable of Real A grid of interpolant values in eV. + id : int + Unique identifier for the filter num_bins : Integral The number of filter bins (always 1 for this filter) stride : Integral @@ -1661,9 +1765,10 @@ class EnergyFunctionFilter(Filter): """ - def __init__(self, energy, y): + def __init__(self, energy, y, filter_id=None): self.energy = energy self.y = y + self.id = filter_id self._stride = None def __eq__(self, other): @@ -1709,6 +1814,7 @@ class EnergyFunctionFilter(Filter): string = type(self).__name__ + '\n' string += '{: <16}=\t{}\n'.format('\tEnergy', self.energy) string += '{: <16}=\t{}\n'.format('\tInterpolant', self.y) + string += '{: <16}=\t{}\n'.format('\tID', self.id) return string @classmethod @@ -1720,8 +1826,9 @@ class EnergyFunctionFilter(Filter): energy = group['energy'].value y = group['y'].value + filter_id = int(group.name.split('/')[-1].lstrip('filter ')) - return cls(energy, y) + return cls(energy, y, filter_id) @classmethod def from_tabulated1d(cls, tab1d): @@ -1792,9 +1899,15 @@ class EnergyFunctionFilter(Filter): def to_xml_element(self): element = ET.Element('filter') + element.set('id', str(self.id)) element.set('type', self.short_name.lower()) - element.set('energy', ' '.join(str(e) for e in self.energy)) - element.set('y', ' '.join(str(y) for y in self.y)) + + subelement = ET.SubElement(element, 'energy') + subelement.text = ' '.join(str(e) for e in self.energy) + + subelement = ET.SubElement(element, 'y') + subelement.text = ' '.join(str(y) for y in self.y) + return element def can_merge(self, other): diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 3eec9a20e..c2e9a6e04 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -351,9 +351,10 @@ class StatePoint(object): tally.derivative = self.tally_derivatives[deriv_id] # Read all filters - n_filters = group['n_filters'].value - for j in range(1, n_filters + 1): - filter_group = group['filter {}'.format(j)] + filters_group = self._f['tallies/filters'] + filter_ids = group['filters'].value + for filter_id in filter_ids: + filter_group = filters_group['filter {}'.format(filter_id)] new_filter = openmc.Filter.from_hdf5(filter_group, meshes=self.meshes) tally.filters.append(new_filter) diff --git a/openmc/tallies.py b/openmc/tallies.py index 0bf87de10..ab0bebc8d 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1076,8 +1076,13 @@ class Tally(object): element.set("name", self.name) # Optional Tally filters - for self_filter in self.filters: - element.append(self_filter.to_xml_element()) + if len(self.filters) > 0: + filters = '' + for filt in self.filters: + filters += '{0} '.format(filt.id) + + subelement = ET.SubElement(element, "filters") + subelement.text = filters.rstrip(' ') # Optional Nuclides if len(self.nuclides) > 0: @@ -3514,6 +3519,14 @@ class Tallies(cv.CheckedList): root_element.append(f.mesh.to_xml_element()) already_written.add(f.mesh) + def _create_filter_subelements(self, root_element): + already_written = set() + for tally in self: + for f in tally.filters: + if f not in already_written: + root_element.append(f.to_xml_element()) + already_written.add(f) + def _create_derivative_subelements(self, root_element): # Get a list of all derivatives referenced in a tally. derivs = [] @@ -3538,6 +3551,7 @@ class Tallies(cv.CheckedList): root_element = ET.Element("tallies") self._create_mesh_subelements(root_element) + self._create_filter_subelements(root_element) self._create_tally_subelements(root_element) self._create_derivative_subelements(root_element) diff --git a/src/initialize.F90 b/src/initialize.F90 index 1852154e8..2ca40cf6f 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -573,9 +573,9 @@ contains ! ======================================================================= ! ADJUST INDICES FOR EACH TALLY FILTER - FILTER_LOOP: do j = 1, size(t % filters) + FILTER_LOOP: do j = 1, size(t % filter) - select type(filt => t % filters(j) % obj) + select type(filt => filters(t % filter(j)) % obj) type is (SurfaceFilter) ! Check if this is a surface filter only for surface currents if (.not. any(t % score_bins == SCORE_CURRENT)) & @@ -695,8 +695,8 @@ contains ! We need distribcell if any tallies have distribcell filters. do i = 1, n_tallies - do j = 1, size(tallies(i) % filters) - select type(filt => tallies(i) % filters(j) % obj) + do j = 1, size(tallies(i) % filter) + select type(filt => filters(tallies(i) % filter(j)) % obj) type is (DistribcellFilter) distribcell_active = .true. end select @@ -722,8 +722,8 @@ contains ! Set the number of bins in all distribcell filters. do i = 1, n_tallies - do j = 1, size(tallies(i) % filters) - select type(filt => tallies(i) % filters(j) % obj) + do j = 1, size(tallies(i) % filter) + select type(filt => filters(tallies(i) % filter(j)) % obj) type is (DistribcellFilter) ! Set the number of bins to the number of instances of the cell. filt % n_bins = cells(filt % cell) % instances @@ -787,8 +787,8 @@ contains ! List all cells referenced in distribcell filters. do i = 1, n_tallies - do j = 1, size(tallies(i) % filters) - select type(filt => tallies(i) % filters(j) % obj) + do j = 1, size(tallies(i) % filter) + select type(filt => filters(tallies(i) % filter(j)) % obj) type is (DistribcellFilter) call cell_list % add(filt % cell) end select diff --git a/src/output.F90 b/src/output.F90 index 9003225ac..344b6c460 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -802,14 +802,14 @@ contains ! to be used for a given tally. ! Initialize bins, filter level, and indentation - matching_bins(1:size(t % filters)) = 0 + matching_bins(1:size(t % filter)) = 0 j = 1 indent = 0 print_bin: do find_bin: do ! Check for no filters - if (size(t % filters) == 0) exit find_bin + if (size(t % filter) == 0) exit find_bin ! Increment bin combination matching_bins(j) = matching_bins(j) + 1 @@ -817,7 +817,7 @@ contains ! ================================================================= ! REACHED END OF BINS FOR THIS FILTER, MOVE TO NEXT FILTER - if (matching_bins(j) > t % filters(j) % obj % n_bins) then + if (matching_bins(j) > filters(t % filter(j)) % obj % n_bins) then ! If this is the first filter, then exit if (j == 1) exit print_bin @@ -830,11 +830,12 @@ contains else ! Check if this is last filter - if (j == size(t % filters)) exit find_bin + if (j == size(t % filter)) exit find_bin ! Print current filter information write(UNIT=unit_tally, FMT='(1X,2A)') repeat(" ", indent), & - trim(t % filters(j) % obj % text_label(matching_bins(j))) + trim(filters(t % filter(j)) % obj % & + text_label(matching_bins(j))) indent = indent + 2 j = j + 1 end if @@ -842,17 +843,18 @@ contains end do find_bin ! Print filter information - if (size(t % filters) > 0) then + if (size(t % filter) > 0) then write(UNIT=unit_tally, FMT='(1X,2A)') repeat(" ", indent), & - trim(t % filters(j) % obj % text_label(matching_bins(j))) + trim(filters(t % filter(j)) % obj % & + text_label(matching_bins(j))) end if ! Determine scoring index for this bin combination -- note that unlike ! in the score_tally subroutine, we have to use max(bins,1) since all ! bins below the lowest filter level will be zeros - if (size(t % filters) > 0) then - filter_index = sum((max(matching_bins(1:size(t % filters)),1) - 1) & + if (size(t % filter) > 0) then + filter_index = sum((max(matching_bins(1:size(t % filter)),1) - 1) & * t % stride) + 1 else filter_index = 1 @@ -860,7 +862,7 @@ contains ! Write results for this filter bin combination score_index = 0 - if (size(t % filters) > 0) indent = indent + 2 + if (size(t % filter) > 0) indent = indent + 2 do n = 1, t % n_nuclide_bins ! Write label for nuclide i_nuclide = t % nuclide_bins(n) @@ -936,7 +938,7 @@ contains end do indent = indent - 2 - if (size(t % filters) == 0) exit print_bin + if (size(t % filter) == 0) exit print_bin end do print_bin @@ -972,19 +974,19 @@ contains ! Get pointer to mesh i_filter_mesh = t % find_filter(FILTER_MESH) i_filter_surf = t % find_filter(FILTER_SURFACE) - select type(filt => t % filters(i_filter_mesh) % obj) + select type(filt => filters(t % filter(i_filter_mesh)) % obj) type is (MeshFilter) m => meshes(filt % mesh) end select ! initialize bins array - matching_bins(1:size(t % filters)) = 1 + matching_bins(1:size(t % filter)) = 1 ! determine how many energy in bins there are i_filter_ein = t % find_filter(FILTER_ENERGYIN) if (i_filter_ein > 0) then print_ebin = .true. - n = t % filters(i_filter_ein) % obj % n_bins + n = filters(t % filter(i_filter_ein)) % obj % n_bins else print_ebin = .false. n = 1 @@ -1021,13 +1023,13 @@ contains ! Write incoming energy bin write(UNIT=unit_tally, FMT='(3X,A)') & - trim(t % filters(i_filter_ein) % obj % text_label( & + trim(filters(t % filter(i_filter_ein)) % obj % text_label( & matching_bins(i_filter_ein))) end if ! Left Surface matching_bins(i_filter_surf) = OUT_LEFT - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Left", & @@ -1035,7 +1037,7 @@ contains trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_LEFT - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Left", & @@ -1044,7 +1046,7 @@ contains ! Right Surface matching_bins(i_filter_surf) = OUT_RIGHT - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Right", & @@ -1052,7 +1054,7 @@ contains trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_RIGHT - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Right", & @@ -1063,7 +1065,7 @@ contains ! Back Surface matching_bins(i_filter_surf) = OUT_BACK - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Back", & @@ -1071,7 +1073,7 @@ contains trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_BACK - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Back", & @@ -1080,7 +1082,7 @@ contains ! Front Surface matching_bins(i_filter_surf) = OUT_FRONT - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Net Current on Front", & @@ -1088,7 +1090,7 @@ contains trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_FRONT - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Net Current on Front", & @@ -1099,7 +1101,7 @@ contains if (n_dim == 3) then ! Bottom Surface matching_bins(i_filter_surf) = OUT_BOTTOM - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Bottom", & @@ -1107,7 +1109,7 @@ contains trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_BOTTOM - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Bottom", & @@ -1116,7 +1118,7 @@ contains ! Top Surface matching_bins(i_filter_surf) = OUT_TOP - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Top", & @@ -1124,7 +1126,7 @@ contains trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) matching_bins(i_filter_surf) = IN_TOP - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Top", & diff --git a/src/state_point.F90 b/src/state_point.F90 index c6790a3ef..b84c7b55e 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -44,8 +44,8 @@ contains integer, allocatable :: id_array(:) integer(HID_T) :: file_id integer(HID_T) :: cmfd_group, tallies_group, tally_group, meshes_group, & - mesh_group, filter_group, derivs_group, deriv_group, & - runtime_group + mesh_group, filters_group, filter_group, derivs_group, & + deriv_group, runtime_group character(MAX_WORD_LEN), allocatable :: str_array(:) character(MAX_FILE_LEN) :: filename type(TallyObject), pointer :: tally @@ -206,6 +206,30 @@ contains call close_group(derivs_group) end if + ! Write number of filters + filters_group = create_group(tallies_group, "filters") + call write_attribute(filters_group, "n_filters", n_filters) + + if (n_filters > 0) then + ! Write IDs of filters + allocate(id_array(n_filters)) + do i = 1, n_filters + id_array(i) = filters(i) % obj % id + end do + call write_attribute(filters_group, "ids", id_array) + deallocate(id_array) + + ! Write filter information + FILTER_LOOP: do i = 1, n_filters + filter_group = create_group(filters_group, "filter " // & + trim(to_str(filters(i) % obj % id))) + call filters(i) % obj % to_statepoint(filter_group) + call close_group(filter_group) + end do FILTER_LOOP + end if + + call close_group(filters_group) + ! Write number of tallies call write_attribute(tallies_group, "n_tallies", n_tallies) @@ -239,15 +263,10 @@ contains end select call write_dataset(tally_group, "n_realizations", & tally % n_realizations) - call write_dataset(tally_group, "n_filters", size(tally % filters)) + call write_dataset(tally_group, "n_filters", size(tally % filter)) - ! Write filter information - FILTER_LOOP: do j = 1, size(tally % filters) - filter_group = create_group(tally_group, "filter " // & - trim(to_str(j))) - call tally % filters(j) % obj % to_statepoint(filter_group) - call close_group(filter_group) - end do FILTER_LOOP + ! Write filter IDs + call write_dataset(tally_group, "filters", tally % filter) ! Set up nuclide bin array and then write allocate(str_array(tally % n_nuclide_bins)) diff --git a/src/tally.F90 b/src/tally.F90 index ebca2bb5d..f222fc55f 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -517,7 +517,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -562,7 +562,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -594,7 +594,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -627,7 +627,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all nuclides in the current material @@ -699,7 +699,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -791,7 +791,7 @@ contains if (dg_filter > 0) then ! declare the delayed group filter type - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! loop over delayed group bins until the corresponding bin is @@ -820,7 +820,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -875,7 +875,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all nuclides in the current material @@ -1681,7 +1681,7 @@ contains if (matxs % get_xs('absorption', p_g, UVW=p_uvw) > ZERO) then if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -1728,7 +1728,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -1764,7 +1764,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -1810,7 +1810,7 @@ contains if (matxs % get_xs('absorption', p_g, UVW=p_uvw) > ZERO) then if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -1900,7 +1900,7 @@ contains if (dg_filter > 0) then ! declare the delayed group filter type - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! loop over delayed group bins until the corresponding bin @@ -1933,7 +1933,7 @@ contains ! Check if the delayed group filter is present if (dg_filter > 0) then - select type(filt => t % filters(dg_filter) % obj) + select type(filt => filters(t % filter(dg_filter)) % obj) type is (DelayedGroupFilter) ! Loop over all delayed group bins and tally to them @@ -2224,9 +2224,10 @@ contains ! Find the first bin in each filter. There may be more than one matching ! bin per filter, but we'll deal with those later. - do i_filt = 1, size(t % filters) - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - NO_BIN_FOUND, matching_bins(i_filt), filter_weights(i_filt)) + do i_filt = 1, size(t % filter) + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, NO_BIN_FOUND, matching_bins(i_filt), & + filter_weights(i_filt)) ! If there are no valid bins for this filter, then there is nothing to ! score and we can move on to the next tally. if (matching_bins(i_filt) == NO_BIN_FOUND) cycle TALLY_LOOP @@ -2238,9 +2239,9 @@ contains FILTER_LOOP: do ! Determine scoring index and weight for this filter combination - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filters))) + filter_weight = product(filter_weights(:size(t % filter))) ! ====================================================================== ! Nuclide logic @@ -2291,30 +2292,30 @@ contains ! Filter logic ! If there are no filters, then we are done. - if (size(t % filters) == 0) exit FILTER_LOOP + if (size(t % filter) == 0) exit FILTER_LOOP ! Increment the filter bins, starting with the last filter. If we get a ! NO_BIN_FOUND for the last filter, it means we finished all valid bins ! for that filter, but next-to-last filter might have more than one ! valid bin so we need to increment that one as well, and so on. - do i_filt = size(t % filters), 1, -1 - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - matching_bins(i_filt), matching_bins(i_filt), & + do i_filt = size(t % filter), 1, -1 + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, matching_bins(i_filt), matching_bins(i_filt), & filter_weights(i_filt)) if (matching_bins(i_filt) /= NO_BIN_FOUND) exit end do ! If we got all NO_BIN_FOUNDs, then we have finished all valid bins for ! each of the filters. Exit the loop. - if (all(matching_bins(:size(t % filters)) == NO_BIN_FOUND)) & + if (all(matching_bins(:size(t % filter)) == NO_BIN_FOUND)) & exit FILTER_LOOP ! Reset all the filters with NO_BIN_FOUND. This will set them back to ! their first valid bin. - do i_filt = 1, size(t % filters) + do i_filt = 1, size(t % filter) if (matching_bins(i_filt) == NO_BIN_FOUND) then - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - matching_bins(i_filt), matching_bins(i_filt), & + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, matching_bins(i_filt), matching_bins(i_filt), & filter_weights(i_filt)) end if end do @@ -2364,9 +2365,10 @@ contains ! Find the first bin in each filter. There may be more than one matching ! bin per filter, but we'll deal with those later. - do i_filt = 1, size(t % filters) - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - NO_BIN_FOUND, matching_bins(i_filt), filter_weights(i_filt)) + do i_filt = 1, size(t % filter) + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, NO_BIN_FOUND, matching_bins(i_filt), & + filter_weights(i_filt)) ! If there are no valid bins for this filter, then there is nothing to ! score and we can move on to the next tally. if (matching_bins(i_filt) == NO_BIN_FOUND) cycle TALLY_LOOP @@ -2378,9 +2380,9 @@ contains FILTER_LOOP: do ! Determine scoring index and weight for this filter combination - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filters))) + filter_weight = product(filter_weights(:size(t % filter))) ! ====================================================================== ! Nuclide logic @@ -2419,30 +2421,30 @@ contains ! Filter logic ! If there are no filters, then we are done. - if (size(t % filters) == 0) exit FILTER_LOOP + if (size(t % filter) == 0) exit FILTER_LOOP ! Increment the filter bins, starting with the last filter. If we get a ! NO_BIN_FOUND for the last filter, it means we finished all valid bins ! for that filter, but next-to-last filter might have more than one ! valid bin so we need to increment that one as well, and so on. - do i_filt = size(t % filters), 1, -1 - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - matching_bins(i_filt), matching_bins(i_filt), & + do i_filt = size(t % filter), 1, -1 + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, matching_bins(i_filt), matching_bins(i_filt), & filter_weights(i_filt)) if (matching_bins(i_filt) /= NO_BIN_FOUND) exit end do ! If we got all NO_BIN_FOUNDs, then we have finished all valid bins for ! each of the filters. Exit the loop. - if (all(matching_bins(:size(t % filters)) == NO_BIN_FOUND)) & + if (all(matching_bins(:size(t % filter)) == NO_BIN_FOUND)) & exit FILTER_LOOP ! Reset all the filters with NO_BIN_FOUND. This will set them back to ! their first valid bin. - do i_filt = 1, size(t % filters) + do i_filt = 1, size(t % filter) if (matching_bins(i_filt) == NO_BIN_FOUND) then - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - matching_bins(i_filt), matching_bins(i_filt), & + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, matching_bins(i_filt), matching_bins(i_filt), & filter_weights(i_filt)) end if end do @@ -2495,7 +2497,7 @@ contains bin_energyout = matching_bins(i) ! declare the energyout filter type - select type(eo_filt => t % filters(i) % obj) + select type(eo_filt => filters(t % filter(i)) % obj) type is (EnergyoutFilter) ! Get number of energies on filter @@ -2557,8 +2559,8 @@ contains (score_bin == SCORE_PROMPT_NU_FISSION .and. g == 0)) then ! determine scoring index and weight for this filter combination - i_filter = sum((matching_bins(1:size(t%filters)) - 1) * t % stride) & - + 1 + i_filter = sum((matching_bins(1:size(t % filter)) - 1) * & + t % stride) + 1 ! Add score to tally !$omp atomic @@ -2576,7 +2578,7 @@ contains if (j > 0) then ! declare the delayed group filter type - select type(dg_filt => t % filters(j) % obj) + select type(dg_filt => filters(t % filter(j)) % obj) type is (DelayedGroupFilter) ! loop over delayed group bins until the corresponding bin is @@ -2590,9 +2592,9 @@ contains ! determine scoring index and weight for this filter ! combination - i_filter = sum((matching_bins(1:size(t%filters)) - 1) * & + i_filter = sum((matching_bins(1:size(t % filter)) - 1) * & t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filters))) + filter_weight = product(filter_weights(:size(t % filter))) call score_fission_delayed_dg(t, d_bin, & score * filter_weight, i_score) @@ -2604,9 +2606,9 @@ contains else ! determine scoring index and weight for this filter combination - i_filter = sum((matching_bins(1:size(t%filters)) - 1) * t % stride)& - + 1 - filter_weight = product(filter_weights(:size(t % filters))) + i_filter = sum((matching_bins(1:size(t % filter)) - 1) * & + t % stride) + 1 + filter_weight = product(filter_weights(:size(t % filter))) ! Add score to tally !$omp atomic @@ -2642,8 +2644,8 @@ contains matching_bins(t % find_filter(FILTER_DELAYEDGROUP)) = d_bin ! determine scoring index and weight on the modified matching_bins - filter_index = sum((matching_bins(1:size(t % filters)) - 1) * t % stride) & - + 1 + filter_index = sum((matching_bins(1:size(t % filter)) - 1) * & + t % stride) + 1 !$omp atomic t % results(RESULT_VALUE, score_index, filter_index) = & @@ -2692,9 +2694,10 @@ contains ! Find the first bin in each filter. There may be more than one matching ! bin per filter, but we'll deal with those later. - do i_filt = 1, size(t % filters) - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - NO_BIN_FOUND, matching_bins(i_filt), filter_weights(i_filt)) + do i_filt = 1, size(t % filter) + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, NO_BIN_FOUND, matching_bins(i_filt), & + filter_weights(i_filt)) ! If there are no valid bins for this filter, then there is nothing to ! score and we can move on to the next tally. if (matching_bins(i_filt) == NO_BIN_FOUND) cycle TALLY_LOOP @@ -2706,9 +2709,9 @@ contains FILTER_LOOP: do ! Determine scoring index and weight for this filter combination - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filters))) + filter_weight = product(filter_weights(:size(t % filter))) ! ====================================================================== ! Nuclide logic @@ -2760,30 +2763,30 @@ contains ! Filter logic ! If there are no filters, then we are done. - if (size(t % filters) == 0) exit FILTER_LOOP + if (size(t % filter) == 0) exit FILTER_LOOP ! Increment the filter bins, starting with the last filter. If we get a ! NO_BIN_FOUND for the last filter, it means we finished all valid bins ! for that filter, but next-to-last filter might have more than one ! valid bin so we need to increment that one as well, and so on. - do i_filt = size(t % filters), 1, -1 - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - matching_bins(i_filt), matching_bins(i_filt), & + do i_filt = size(t % filter), 1, -1 + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, matching_bins(i_filt), matching_bins(i_filt), & filter_weights(i_filt)) if (matching_bins(i_filt) /= NO_BIN_FOUND) exit end do ! If we got all NO_BIN_FOUNDs, then we have finished all valid bins for ! each of the filters. Exit the loop. - if (all(matching_bins(:size(t % filters)) == NO_BIN_FOUND)) & + if (all(matching_bins(:size(t % filter)) == NO_BIN_FOUND)) & exit FILTER_LOOP ! Reset all the filters with NO_BIN_FOUND. This will set them back to ! their first valid bin. - do i_filt = 1, size(t % filters) + do i_filt = 1, size(t % filter) if (matching_bins(i_filt) == NO_BIN_FOUND) then - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - matching_bins(i_filt), matching_bins(i_filt), & + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, matching_bins(i_filt), matching_bins(i_filt), & filter_weights(i_filt)) end if end do @@ -2847,9 +2850,10 @@ contains ! Find the first bin in each filter. There may be more than one matching ! bin per filter, but we'll deal with those later. - do i_filt = 1, size(t % filters) - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - NO_BIN_FOUND, matching_bins(i_filt), filter_weights(i_filt)) + do i_filt = 1, size(t % filter) + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, NO_BIN_FOUND, matching_bins(i_filt), & + filter_weights(i_filt)) ! If there are no valid bins for this filter, then there is nothing to ! score and we can move on to the next tally. if (matching_bins(i_filt) == NO_BIN_FOUND) cycle TALLY_LOOP @@ -2861,9 +2865,9 @@ contains FILTER_LOOP: do ! Determine scoring index and weight for this filter combination - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filters))) + filter_weight = product(filter_weights(:size(t % filter))) ! ====================================================================== ! Nuclide logic @@ -2915,30 +2919,30 @@ contains ! Filter logic ! If there are no filters, then we are done. - if (size(t % filters) == 0) exit FILTER_LOOP + if (size(t % filter) == 0) exit FILTER_LOOP ! Increment the filter bins, starting with the last filter. If we get a ! NO_BIN_FOUND for the last filter, it means we finished all valid bins ! for that filter, but next-to-last filter might have more than one ! valid bin so we need to increment that one as well, and so on. - do i_filt = size(t % filters), 1, -1 - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - matching_bins(i_filt), matching_bins(i_filt), & + do i_filt = size(t % filter), 1, -1 + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, matching_bins(i_filt), matching_bins(i_filt), & filter_weights(i_filt)) if (matching_bins(i_filt) /= NO_BIN_FOUND) exit end do ! If we got all NO_BIN_FOUNDs, then we have finished all valid bins for ! each of the filters. Exit the loop. - if (all(matching_bins(:size(t % filters)) == NO_BIN_FOUND)) & + if (all(matching_bins(:size(t % filter)) == NO_BIN_FOUND)) & exit FILTER_LOOP ! Reset all the filters with NO_BIN_FOUND. This will set them back to ! their first valid bin. - do i_filt = 1, size(t % filters) + do i_filt = 1, size(t % filter) if (matching_bins(i_filt) == NO_BIN_FOUND) then - call t % filters(i_filt) % obj % get_next_bin(p, t % estimator, & - matching_bins(i_filt), matching_bins(i_filt), & + call filters(t % filter(i_filt)) % obj % get_next_bin(p, & + t % estimator, matching_bins(i_filt), matching_bins(i_filt), & filter_weights(i_filt)) end if end do @@ -3009,7 +3013,7 @@ contains i_filter_energy = t % find_filter(FILTER_ENERGYIN) ! Get pointer to mesh - select type(filt => t % filters(i_filter_mesh) % obj) + select type(filt => filters(t % filter(i_filter_mesh)) % obj) type is (MeshFilter) m => meshes(filt % mesh) end select @@ -3044,7 +3048,7 @@ contains ! Determine incoming energy bin. We need to tell the energy filter this ! is a tracklength tally so it uses the pre-collision energy. if (i_filter_energy > 0) then - call t % filters(i_filter_energy) % obj % get_next_bin(p, & + call filters(t % filter(i_filter_energy)) % obj % get_next_bin(p, & ESTIMATOR_TRACKLENGTH, NO_BIN_FOUND, & matching_bins(i_filter_energy), filt_score) if (matching_bins(i_filter_energy) == NO_BIN_FOUND) cycle @@ -3106,7 +3110,7 @@ contains matching_bins(i_filter_surf) = d1 * 4 - 1 matching_bins(i_filter_mesh) = & mesh_indices_to_bin(m, ijk0) - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 !$omp atomic t % results(RESULT_VALUE, 1, filter_index) = & @@ -3142,7 +3146,7 @@ contains matching_bins(i_filter_surf) = d1 * 4 - 2 matching_bins(i_filter_mesh) = & mesh_indices_to_bin(m, ijk0) - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 !$omp atomic t % results(RESULT_VALUE, 1, filter_index) = & @@ -3162,7 +3166,7 @@ contains matching_bins(i_filter_surf) = d1 * 4 - 3 matching_bins(i_filter_mesh) = & mesh_indices_to_bin(m, ijk0) - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 !$omp atomic t % results(RESULT_VALUE, 1, filter_index) = & @@ -3198,7 +3202,7 @@ contains matching_bins(i_filter_surf) = d1 * 4 matching_bins(i_filter_mesh) = & mesh_indices_to_bin(m, ijk0) - filter_index = sum((matching_bins(1:size(t % filters)) - 1) & + filter_index = sum((matching_bins(1:size(t % filter)) - 1) & * t % stride) + 1 !$omp atomic t % results(RESULT_VALUE, 1, filter_index) = & diff --git a/src/trigger.F90 b/src/trigger.F90 index 503b53ca8..32f2549c8 100644 --- a/src/trigger.F90 +++ b/src/trigger.F90 @@ -167,7 +167,7 @@ contains else ! Initialize bins, filter level - matching_bins(1:size(t % filters)) = 0 + matching_bins(1:size(t % filter)) = 0 FILTER_LOOP: do filter_index = 1, t % total_filter_bins @@ -267,7 +267,7 @@ contains end if end if end do NUCLIDE_LOOP - if (size(t % filters) == 0) exit FILTER_LOOP + if (size(t % filter) == 0) exit FILTER_LOOP end do FILTER_LOOP end if end do TRIGGER_LOOP @@ -303,19 +303,19 @@ contains ! Get pointer to mesh i_filter_mesh = t % find_filter(FILTER_MESH) i_filter_surf = t % find_filter(FILTER_SURFACE) - select type(filt => t % filters(i_filter_mesh) % obj) + select type(filt => filters(t % filter(i_filter_mesh)) % obj) type is (MeshFilter) m => meshes(filt % mesh) end select ! initialize bins array - matching_bins(1:size(t % filters)) = 1 + matching_bins(1:size(t % filter)) = 1 ! determine how many energyin bins there are i_filter_ein = t % find_filter(FILTER_ENERGYIN) if (i_filter_ein > 0) then print_ebin = .true. - n = t % filters(i_filter_ein) % obj % n_bins + n = filters(t % filter(i_filter_ein)) % obj % n_bins else print_ebin = .false. n = 1 @@ -341,7 +341,7 @@ contains ! Left Surface matching_bins(i_filter_surf) = OUT_LEFT filter_index = & - sum((matching_bins(1:size(t % filters)) - 1) * t % stride) + 1 + sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -354,7 +354,7 @@ contains ! Right Surface matching_bins(i_filter_surf) = OUT_RIGHT filter_index = & - sum((matching_bins(1:size(t % filters)) - 1) * t % stride) + 1 + sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -367,7 +367,7 @@ contains ! Back Surface matching_bins(i_filter_surf) = OUT_BACK filter_index = & - sum((matching_bins(1:size(t % filters)) - 1) * t % stride) + 1 + sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -380,7 +380,7 @@ contains ! Front Surface matching_bins(i_filter_surf) = OUT_FRONT filter_index = & - sum((matching_bins(1:size(t % filters)) - 1) * t % stride) + 1 + sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -393,7 +393,7 @@ contains ! Bottom Surface matching_bins(i_filter_surf) = OUT_BOTTOM filter_index = & - sum((matching_bins(1:size(t % filters)) - 1) * t % stride) + 1 + sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -406,7 +406,7 @@ contains ! Top Surface matching_bins(i_filter_surf) = OUT_TOP filter_index = & - sum((matching_bins(1:size(t % filters)) - 1) * t % stride) + 1 + sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev From 60dcf722bdbbb85ba8b28d5801ac9651c388b8ba Mon Sep 17 00:00:00 2001 From: amandalund Date: Mon, 27 Mar 2017 14:24:42 -0500 Subject: [PATCH 05/18] Debugging --- src/cmfd_input.F90 | 3 +-- src/global.F90 | 2 +- src/input_xml.F90 | 34 +++++++++++++++++++--------------- src/tally_filter.F90 | 2 +- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index 1fc15e845..efcccf053 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -260,7 +260,7 @@ contains type(XMLNode), intent(in) :: root ! XML root element logical :: energy_filters - integer :: i, j ! loop counter + integer :: i ! loop counter integer :: n ! size of arrays in mesh specification integer :: ng ! number of energy groups (default 1) integer :: n_filter ! number of filters @@ -269,7 +269,6 @@ contains real(8) :: rarray3(3) ! temp double array type(TallyObject), pointer :: t type(RegularMesh), pointer :: m - type(TallyFilterContainer), allocatable :: temp_filters(:) ! temporary filters type(XMLNode) :: node_mesh ! Set global variables if they are 0 (this can happen if there is no tally diff --git a/src/global.F90 b/src/global.F90 index 551a3b4f2..815063344 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -141,7 +141,7 @@ module global type(RegularMesh), allocatable, target :: meshes(:) type(TallyObject), allocatable, target :: tallies(:) - type(TallyFilterContainer), allocatable :: filters(:) + type(TallyFilterContainer), allocatable, target :: filters(:) integer, allocatable :: matching_bins(:) real(8), allocatable :: filter_weights(:) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index e6aeae324..436d9a009 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2613,6 +2613,7 @@ contains integer :: k ! another loop index integer :: l ! another loop index integer :: id ! user-specified identifier + integer :: filter_id ! user-specified identifier for filter integer :: i_mesh ! index in meshes array integer :: i_filt ! index in filters array integer :: n ! size of arrays in mesh specification @@ -2955,15 +2956,15 @@ contains ! Copy filter id if (check_for_node(node_filt, "id")) then - call get_node_value(node_filt, "id", f % id) + call get_node_value(node_filt, "id", filter_id) else call fatal_error("Must specify id for filter in tally XML file.") end if ! Check to make sure 'id' hasn't been used - if (filter_dict % has_key(f % id)) then + if (filter_dict % has_key(filter_id)) then call fatal_error("Two or more filters use the same unique ID: " & - // to_str(f % id)) + // to_str(filter_id)) end if ! Convert filter type to lower case @@ -2976,13 +2977,13 @@ contains select case(temp_str) case ("energy", "energyout", "mu", "polar", "azimuthal") if (.not. check_for_node(node_filt, "bins")) then - call fatal_error("Bins not set in filter " // trim(to_str(f % id))) + call fatal_error("Bins not set in filter " // trim(to_str(filter_id))) end if n_words = node_word_count(node_filt, "bins") case ("mesh", "universe", "material", "cell", "distribcell", & "cellborn", "surface", "delayedgroup") if (.not. check_for_node(node_filt, "bins")) then - call fatal_error("Bins not set in filter " // trim(to_str(f % id))) + call fatal_error("Bins not set in filter " // trim(to_str(filter_id))) end if n_words = node_word_count(node_filt, "bins") end select @@ -3074,7 +3075,7 @@ contains m => meshes(i_mesh) else call fatal_error("Could not find mesh " // trim(to_str(id)) & - // " specified on filter " // trim(to_str(f % id))) + // " specified on filter " // trim(to_str(filter_id))) end if ! Determine number of bins @@ -3182,7 +3183,7 @@ contains else call fatal_error("Number of bins for mu filter must be& & greater than 1 on filter " & - // trim(to_str(f % id)) // ".") + // trim(to_str(filter_id)) // ".") end if end if end select @@ -3213,7 +3214,7 @@ contains else call fatal_error("Number of bins for polar filter must be& & greater than 1 on filter " & - // trim(to_str(f % id)) // ".") + // trim(to_str(filter_id)) // ".") end if end if end select @@ -3245,7 +3246,7 @@ contains else call fatal_error("Number of bins for azimuthal filter must be& & greater than 1 on filter " & - // trim(to_str(f % id)) // ".") + // trim(to_str(filter_id)) // ".") end if end if end select @@ -3265,7 +3266,7 @@ contains ! Allocate and store energy grid. if (.not. check_for_node(node_filt, "energy")) then call fatal_error("Energy grid not specified for EnergyFunction & - &filter on filter " // trim(to_str(f % id))) + &filter on filter " // trim(to_str(filter_id))) end if n_words = node_word_count(node_filt, "energy") allocate(filt % energy(n_words)) @@ -3274,7 +3275,7 @@ contains ! Allocate and store interpolant values. if (.not. check_for_node(node_filt, "y")) then call fatal_error("y values not specified for EnergyFunction & - &filter on filter " // trim(to_str(f % id))) + &filter on filter " // trim(to_str(filter_id))) end if n_words = node_word_count(node_filt, "y") allocate(filt % y(n_words)) @@ -3285,12 +3286,15 @@ contains ! Specified filter is invalid, raise error call fatal_error("Unknown filter type '" & // trim(temp_str) // "' on filter " & - // trim(to_str(f % id)) // ".") + // trim(to_str(filter_id)) // ".") end select + ! Set filter id + f % obj % id = filter_id + ! Add filter to dictionary - call filter_dict % add_key(f % id, i) + call filter_dict % add_key(filter_id, i) end do READ_FILTERS @@ -3353,12 +3357,12 @@ contains f => filters(i_filt) else call fatal_error("Could not find filter " & - // trim(to_str(temp_filter(j))) & // " specified on tally " & + // trim(to_str(temp_filter(j))) // " specified on tally " & // trim(to_str(t % id))) end if ! Set the filter index in the tally find_filter array - select type (f % obj) + select type (filt => f % obj) type is (DistribcellFilter) t % find_filter(FILTER_DISTRIBCELL) = j type is (CellFilter) diff --git a/src/tally_filter.F90 b/src/tally_filter.F90 index 64abec87c..d41759309 100644 --- a/src/tally_filter.F90 +++ b/src/tally_filter.F90 @@ -1669,7 +1669,7 @@ contains ! Allocate filters array with increased size deallocate(filters) - allocate(filters(size(temp)) + allocate(filters(size(temp))) ! Move filters back from temporary array to filters array do i = 1, n_filters From 8b1953b7e1acbb1f65727e2f7c5ce1c75acb253e Mon Sep 17 00:00:00 2001 From: amandalund Date: Mon, 27 Mar 2017 17:33:28 -0500 Subject: [PATCH 06/18] Fix initialize --- src/cmfd_input.F90 | 1 + src/initialize.F90 | 29 +++++++++++------------------ src/input_xml.F90 | 1 + src/tally_filter.F90 | 3 +++ 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index efcccf053..d602414bd 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -445,6 +445,7 @@ contains OUT_BACK, IN_BACK, IN_FRONT, OUT_FRONT, & OUT_BOTTOM, IN_BOTTOM, IN_TOP, OUT_TOP /) end if + filt % current = .true. ! Add filter to dictionary call filter_dict % add_key(filt % id, i_filt) end select diff --git a/src/initialize.F90 b/src/initialize.F90 index 2ca40cf6f..566b5aad7 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -432,7 +432,6 @@ contains integer :: id ! user-specified id type(Cell), pointer :: c => null() class(Lattice), pointer :: lat => null() - type(TallyObject), pointer :: t => null() do i = 1, n_cells ! ======================================================================= @@ -567,26 +566,20 @@ contains end do - TALLY_LOOP: do i = 1, n_tallies - t => tallies(i) + ! ======================================================================= + ! ADJUST INDICES FOR EACH TALLY FILTER - ! ======================================================================= - ! ADJUST INDICES FOR EACH TALLY FILTER + FILTER_LOOP: do i = 1, n_filters - FILTER_LOOP: do j = 1, size(t % filter) + select type(filt => filters(i) % obj) + type is (SurfaceFilter) + ! Check if this is a surface filter only for surface currents + if (.not. filt % current) call filt % initialize() + class default + call filt % initialize() + end select - select type(filt => filters(t % filter(j)) % obj) - type is (SurfaceFilter) - ! Check if this is a surface filter only for surface currents - if (.not. any(t % score_bins == SCORE_CURRENT)) & - call filt % initialize() - class default - call filt % initialize() - end select - - end do FILTER_LOOP - - end do TALLY_LOOP + end do FILTER_LOOP end subroutine adjust_indices diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 436d9a009..db06814cc 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -3842,6 +3842,7 @@ contains OUT_BOTTOM, OUT_TOP, IN_LEFT, IN_RIGHT, IN_BACK, & IN_FRONT, IN_BOTTOM, IN_TOP /) end if + filt % current = .true. end select t % find_filter(FILTER_SURFACE) = n_filter diff --git a/src/tally_filter.F90 b/src/tally_filter.F90 index d41759309..0c316f73b 100644 --- a/src/tally_filter.F90 +++ b/src/tally_filter.F90 @@ -103,6 +103,9 @@ module tally_filter !=============================================================================== type, extends(TallyFilter) :: SurfaceFilter integer, allocatable :: surfaces(:) + + ! True if this filter is used for surface currents + logical :: current = .false. contains procedure :: get_next_bin => get_next_bin_surface procedure :: to_statepoint => to_statepoint_surface From 3670d6eda9149d942a75007a8bf94c3ce7635bf8 Mon Sep 17 00:00:00 2001 From: amandalund Date: Tue, 28 Mar 2017 15:19:05 -0500 Subject: [PATCH 07/18] Fix writing identical filters with different user IDs to tallies.xml --- openmc/tallies.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index ab0bebc8d..7396635d0 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3468,6 +3468,20 @@ class Tallies(cv.CheckedList): # Continue iterating from the first loop break + def remove_duplicate_filters(self): + """Search all tallies for any identical filters and set the IDs of + identical filters to the same value. This prevents a filter from being + written multiple times to the tallies.xml input file. + + """ + + for tally1 in self: + for filter1 in tally1.filters: + for tally2 in self: + for filter2 in tally2.filters: + if filter1 == filter2: + filter2.id = filter1.id + def add_mesh(self, mesh): """Add a mesh to the file @@ -3539,16 +3553,23 @@ class Tallies(cv.CheckedList): for d in derivs: root_element.append(d.to_xml_element()) - def export_to_xml(self, path='tallies.xml'): + def export_to_xml(self, path='tallies.xml', reduce_filters=True): """Create a tallies.xml file that can be used for a simulation. Parameters ---------- path : str Path to file to write. Defaults to 'tallies.xml'. + reduce_filters : bool + Indicates whether duplicate filters should be removed. This + prevents identical filters with different user IDs from being + written to the tallies.xml input file. Defaults to True. """ + if reduce_filters: + self.remove_duplicate_filters() + root_element = ET.Element("tallies") self._create_mesh_subelements(root_element) self._create_filter_subelements(root_element) From a9eff2cfdd19d8e71429c36fd333a95e3539300b Mon Sep 17 00:00:00 2001 From: amandalund Date: Tue, 28 Mar 2017 16:31:40 -0500 Subject: [PATCH 08/18] Fix statepoint --- openmc/statepoint.py | 24 ++++++++++++++++++++++-- src/state_point.F90 | 11 +++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index c2e9a6e04..23aad6427 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -51,6 +51,9 @@ class StatePoint(object): Date and time when simulation began entropy : numpy.ndarray Shannon entropy of fission source at each batch + filters : dict + Dictionary whose keys are filter IDs and whose values are Filter + objects generations_per_batch : int Number of fission generations per batch global_tallies : numpy.ndarray of compound datatype @@ -66,8 +69,8 @@ class StatePoint(object): Cross-product of absorption and tracklength estimates of k-effective k_generation : numpy.ndarray Estimate of k-effective for each batch/generation - meshes : dict - Dictionary whose keys are mesh IDs and whose values are Mesh objects + MESHES : DICT + DICTIONARY WHOSE KEYS ARE MESH IDS AND WHOSE VALUES ARE MESH OBJECTS n_batches : int Number of batches n_inactive : int @@ -111,6 +114,7 @@ class StatePoint(object): def __init__(self, filename, autolink=True): self._f = h5py.File(filename, 'r') self._meshes = {} + self._filters = {} self._tallies = {} self._derivs = {} @@ -119,6 +123,7 @@ class StatePoint(object): # Set flags for what data has been read self._meshes_read = False + self._filters_read = False self._tallies_read = False self._summary = None self._global_tallies = None @@ -185,6 +190,20 @@ class StatePoint(object): else: return None + @property + def filters(self): + if not self._filters_read: + filters_group = self._f['tallies/filters'] + + # Iterate over all Filters + for group in filters_group.values(): + new_filter = openmc.Filter.from_hdf5(group, meshes=self.meshes) + self._filters[new_filter.id] = new_filter + + self._filters_read = True + + return self._filters + @property def generations_per_batch(self): if self.run_mode == 'eigenvalue': @@ -353,6 +372,7 @@ class StatePoint(object): # Read all filters filters_group = self._f['tallies/filters'] filter_ids = group['filters'].value + n_filters = len(filter_ids) for filter_id in filter_ids: filter_group = filters_group['filter {}'.format(filter_id)] new_filter = openmc.Filter.from_hdf5(filter_group, diff --git a/src/state_point.F90 b/src/state_point.F90 index b84c7b55e..206e6cc8d 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -265,8 +265,15 @@ contains tally % n_realizations) call write_dataset(tally_group, "n_filters", size(tally % filter)) - ! Write filter IDs - call write_dataset(tally_group, "filters", tally % filter) + if (size(tally % filter) > 0) then + ! Write IDs of filters + allocate(id_array(size(tally % filter))) + do j = 1, size(tally % filter) + id_array(j) = filters(tally % filter(j)) % obj % id + end do + call write_dataset(tally_group, "filters", id_array) + deallocate(id_array) + end if ! Set up nuclide bin array and then write allocate(str_array(tally % n_nuclide_bins)) From 08341f9c0cf831fd652a510eb6e0df3d78fc67bd Mon Sep 17 00:00:00 2001 From: amandalund Date: Wed, 29 Mar 2017 21:28:56 -0500 Subject: [PATCH 09/18] Fix statepoint and input XML; update test inputs --- openmc/statepoint.py | 17 +- src/cmfd_input.F90 | 29 +- src/input_xml.F90 | 30 +- src/state_point.F90 | 2 +- tests/test_asymmetric_lattice/inputs_true.dat | 5 +- tests/test_cmfd_feed/tallies.xml | 7 +- tests/test_cmfd_nofeed/tallies.xml | 7 +- tests/test_complex_cell/tallies.xml | 9 +- tests/test_confidence_intervals/tallies.xml | 9 +- tests/test_diff_tally/inputs_true.dat | 51 +- tests/test_diff_tally/test_diff_tally.py | 1 + tests/test_energy_cutoff/inputs_true.dat | 5 +- .../case-1/tallies.xml | 26 +- .../case-2/tallies.xml | 13 +- .../case-3/tallies.xml | 78 ++- .../case-4/tallies.xml | 13 +- tests/test_filter_energyfun/inputs_true.dat | 6 +- tests/test_filter_mesh/inputs_true.dat | 21 +- tests/test_mg_tallies/inputs_true.dat | 78 ++- .../inputs_true.dat | 117 ++-- .../inputs_true.dat | 636 ++++++------------ .../inputs_true.dat | 217 ++---- tests/test_mgxs_library_hdf5/inputs_true.dat | 636 ++++++------------ tests/test_mgxs_library_mesh/inputs_true.dat | 217 ++---- .../inputs_true.dat | 636 ++++++------------ .../inputs_true.dat | 519 +++++--------- tests/test_score_current/tallies.xml | 15 +- tests/test_sourcepoint_restart/tallies.xml | 26 +- tests/test_statepoint_restart/tallies.xml | 26 +- tests/test_tallies/inputs_true.dat | 104 ++- tests/test_tally_aggregation/inputs_true.dat | 9 +- tests/test_tally_arithmetic/inputs_true.dat | 19 +- tests/test_tally_assumesep/tallies.xml | 23 +- tests/test_tally_slice_merge/inputs_true.dat | 21 +- 34 files changed, 1402 insertions(+), 2226 deletions(-) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 23aad6427..f0085395c 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -370,14 +370,15 @@ class StatePoint(object): tally.derivative = self.tally_derivatives[deriv_id] # Read all filters - filters_group = self._f['tallies/filters'] - filter_ids = group['filters'].value - n_filters = len(filter_ids) - for filter_id in filter_ids: - filter_group = filters_group['filter {}'.format(filter_id)] - new_filter = openmc.Filter.from_hdf5(filter_group, - meshes=self.meshes) - tally.filters.append(new_filter) + n_filters = group['n_filters'].value + if n_filters > 0: + filter_ids = group['filters'].value + filters_group = self._f['tallies/filters'] + for filter_id in filter_ids: + filter_group = filters_group['filter {}'.format(filter_id)] + new_filter = openmc.Filter.from_hdf5(filter_group, + meshes=self.meshes) + tally.filters.append(new_filter) # Read nuclide bins nuclide_names = group['nuclides'].value diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index d602414bd..8b67f7a8f 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -379,9 +379,9 @@ contains ! Determine number of filters energy_filters = check_for_node(node_mesh, "energy") if (energy_filters) then - n_cmfd_filters = 4 + n_cmfd_filters = 5 else - n_cmfd_filters = 2 + n_cmfd_filters = 3 end if ! Extend filters array so we can add CMFD filters @@ -429,6 +429,21 @@ contains end select end if + ! Duplicate the mesh filter for the surface current tally since other + ! tallies use this filter and we need to change the dimension + i_filt = i_filt + 1 + allocate(MeshFilter :: filters(i_filt) % obj) + select type (filt => filters(i_filt) % obj) + type is (MeshFilter) + filt % id = i_filt + ! We need to increase the dimension by one since we also need + ! currents coming into and out of the boundary mesh cells. + filt % n_bins = product(m % dimension + 1) + filt % mesh = n_user_meshes + 1 + ! Add filter to dictionary + call filter_dict % add_key(filt % id, i_filt) + end select + ! Set up surface filter i_filt = i_filt + 1 allocate(SurfaceFilter :: filters(i_filt) % obj) @@ -565,11 +580,11 @@ contains ! Set the surface filter index in the tally find_filter array n_filter = n_filter + 1 - t % find_filter(FILTER_SURFACE) = n_cmfd_filters + t % find_filter(FILTER_SURFACE) = n_filter ! Allocate and set filters allocate(t % filter(n_filter)) - t % filter(1) = n_user_filters + 1 + t % filter(1) = n_user_filters + n_cmfd_filters - 1 t % filter(n_filter) = n_user_filters + n_cmfd_filters if (energy_filters) then t % filter(2) = n_user_filters + 2 @@ -587,12 +602,6 @@ contains ! Set macro bins t % score_bins(1) = SCORE_CURRENT t % type = TALLY_SURFACE_CURRENT - - ! We need to increase the dimension by one since we also need - ! currents coming into and out of the boundary mesh cells. - i_filt = t % filter(t % find_filter(FILTER_MESH)) - filters(i_filt) % obj % n_bins = product(m % dimension + 1) - end if end do diff --git a/src/input_xml.F90 b/src/input_xml.F90 index db06814cc..b1c0cc49c 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -3348,7 +3348,9 @@ contains ! Allocate and store filter user ids allocate(temp_filter(n_filter)) - call get_node_array(node_tal, "filters", temp_filter) + if (n_filter > 0) then + call get_node_array(node_tal, "filters", temp_filter) + end if do j = 1, n_filter ! Get pointer to filter @@ -3798,19 +3800,6 @@ contains &filter.") end if - ! Declare the type of the mesh filter - select type(filt => filters(i_filt) % obj) - type is (MeshFilter) - - ! Get pointer to mesh - i_mesh = filt % mesh - m => meshes(i_mesh) - - ! We need to increase the dimension by one since we also need - ! currents coming into and out of the boundary mesh cells. - filt % n_bins = product(m % dimension + 1) - end select - ! Copy filter indices to temporary array allocate(temp_filter(size(t % filter) + 1)) temp_filter(1:size(t % filter)) = t % filter @@ -3826,10 +3815,14 @@ contains ! Increment number of user filters n_user_filters = n_user_filters + 1 + ! Get index of the new surface filter + i_filt = n_filters + ! Add surface filter - allocate(SurfaceFilter :: filters(n_filters) % obj) - select type (filt => filters(n_filters) % obj) + allocate(SurfaceFilter :: filters(i_filt) % obj) + select type (filt => filters(i_filt) % obj) type is (SurfaceFilter) + filt % id = i_filt filt % n_bins = 4 * m % n_dimension allocate(filt % surfaces(4 * m % n_dimension)) if (m % n_dimension == 1) then @@ -3843,12 +3836,15 @@ contains IN_FRONT, IN_BOTTOM, IN_TOP /) end if filt % current = .true. + + ! Add filter to dictionary + call filter_dict % add_key(filt % id, i_filt) end select t % find_filter(FILTER_SURFACE) = n_filter + t % filter(n_filter) = i_filt case ('events') t % score_bins(j) = SCORE_EVENTS - case ('elastic', '(n,elastic)') t % score_bins(j) = ELASTIC case ('(n,2nd)') diff --git a/src/state_point.F90 b/src/state_point.F90 index 206e6cc8d..e4c9a43ae 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -263,8 +263,8 @@ contains end select call write_dataset(tally_group, "n_realizations", & tally % n_realizations) - call write_dataset(tally_group, "n_filters", size(tally % filter)) + call write_dataset(tally_group, "n_filters", size(tally % filter)) if (size(tally % filter) > 0) then ! Write IDs of filters allocate(id_array(size(tally % filter))) diff --git a/tests/test_asymmetric_lattice/inputs_true.dat b/tests/test_asymmetric_lattice/inputs_true.dat index 32745dad1..3e8b22fc6 100644 --- a/tests/test_asymmetric_lattice/inputs_true.dat +++ b/tests/test_asymmetric_lattice/inputs_true.dat @@ -217,8 +217,11 @@ + + 27 + - + 10000 nu-fission diff --git a/tests/test_cmfd_feed/tallies.xml b/tests/test_cmfd_feed/tallies.xml index 37edcecc2..c86971114 100644 --- a/tests/test_cmfd_feed/tallies.xml +++ b/tests/test_cmfd_feed/tallies.xml @@ -8,8 +8,13 @@ 10 1 1 + + mesh + 1 + + - + 1 flux diff --git a/tests/test_cmfd_nofeed/tallies.xml b/tests/test_cmfd_nofeed/tallies.xml index 37edcecc2..c86971114 100644 --- a/tests/test_cmfd_nofeed/tallies.xml +++ b/tests/test_cmfd_nofeed/tallies.xml @@ -8,8 +8,13 @@ 10 1 1 + + mesh + 1 + + - + 1 flux diff --git a/tests/test_complex_cell/tallies.xml b/tests/test_complex_cell/tallies.xml index d1a7d387e..e0509e6a8 100644 --- a/tests/test_complex_cell/tallies.xml +++ b/tests/test_complex_cell/tallies.xml @@ -1,7 +1,14 @@ + + + cell + 1 2 3 4 + + - + 1 total + diff --git a/tests/test_confidence_intervals/tallies.xml b/tests/test_confidence_intervals/tallies.xml index 0e1fe213c..65ff255fb 100644 --- a/tests/test_confidence_intervals/tallies.xml +++ b/tests/test_confidence_intervals/tallies.xml @@ -1,9 +1,14 @@ + + cell + 1 + + - + 1 flux - \ No newline at end of file + diff --git a/tests/test_diff_tally/inputs_true.dat b/tests/test_diff_tally/inputs_true.dat index 0d75e48c6..0385224d5 100644 --- a/tests/test_diff_tally/inputs_true.dat +++ b/tests/test_diff_tally/inputs_true.dat @@ -310,122 +310,123 @@ + + 1 3 + + + 0.0 0.625 20000000.0 + - + 10000 flux 1 - + 10000 flux 2 - + 10000 flux 3 - + 10000 flux 4 - + 10000 flux 5 - + 10000 total U235 total absorption scatter fission nu-fission 1 - + 10000 total U235 total absorption scatter fission nu-fission 2 - + 10000 total U235 total absorption scatter fission nu-fission 3 - + 10000 total U235 total absorption scatter fission nu-fission 4 - + 10000 total U235 total absorption scatter fission nu-fission 5 - + 10000 absorption analog 1 - + 10000 absorption analog 2 - + 10000 absorption analog 3 - + 10000 absorption analog 4 - + 10000 absorption analog 5 - - + 10000 10001 total U235 nu-fission scatter 1 - - + 10000 10001 total U235 nu-fission scatter 2 - - + 10000 10001 U235 nu-fission scatter 3 - - + 10000 10001 U235 nu-fission scatter 4 - - + 10000 10001 U235 nu-fission scatter 5 diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index 84aa18156..51e4cd5eb 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -127,6 +127,7 @@ class DiffTallyTestHarness(PyAPITestHarness): # Extract the relevant data as a CSV string. cols = ('d_material', 'd_nuclide', 'd_variable', 'score', 'mean', 'std. dev.') + print(df.to_csv(None, columns=cols, index=False, float_format='%.7e')) return df.to_csv(None, columns=cols, index=False, float_format='%.7e') diff --git a/tests/test_energy_cutoff/inputs_true.dat b/tests/test_energy_cutoff/inputs_true.dat index 7f67288d1..a2d2967c0 100644 --- a/tests/test_energy_cutoff/inputs_true.dat +++ b/tests/test_energy_cutoff/inputs_true.dat @@ -32,8 +32,11 @@ + + 0.0 4.0 + - + 10000 flux diff --git a/tests/test_filter_distribcell/case-1/tallies.xml b/tests/test_filter_distribcell/case-1/tallies.xml index e9b952a55..1e7061f21 100644 --- a/tests/test_filter_distribcell/case-1/tallies.xml +++ b/tests/test_filter_distribcell/case-1/tallies.xml @@ -1,22 +1,24 @@ + + distribcell + 201 + + + + cell + 201 + + - - - 201 - - - total + 1 + total - - - 201 - - - total + 2 + total diff --git a/tests/test_filter_distribcell/case-2/tallies.xml b/tests/test_filter_distribcell/case-2/tallies.xml index 55738312b..b2efa76a5 100644 --- a/tests/test_filter_distribcell/case-2/tallies.xml +++ b/tests/test_filter_distribcell/case-2/tallies.xml @@ -1,13 +1,14 @@ + + cell + 201 203 205 207 + + - - - 201 203 205 207 - - - total + 1 + total diff --git a/tests/test_filter_distribcell/case-3/tallies.xml b/tests/test_filter_distribcell/case-3/tallies.xml index 30c9426e0..aed192854 100644 --- a/tests/test_filter_distribcell/case-3/tallies.xml +++ b/tests/test_filter_distribcell/case-3/tallies.xml @@ -1,58 +1,64 @@ + + cell + 1 + + + + distribcell + 1 + + + + cell + 60 + + + + distribcell + 60 + + + + cell + 27 + + + + distribcell + 27 + + - - - 1 - - - total + 1 + total - - - 1 - - - total + 2 + total - - - 60 - - - total + 3 + total - - - 60 - - - total + 4 + total - - - 27 - - - total + 5 + total - - - 27 - - - total + 6 + total diff --git a/tests/test_filter_distribcell/case-4/tallies.xml b/tests/test_filter_distribcell/case-4/tallies.xml index b46de5f4e..b923c030b 100644 --- a/tests/test_filter_distribcell/case-4/tallies.xml +++ b/tests/test_filter_distribcell/case-4/tallies.xml @@ -1,7 +1,14 @@ - - + + + distribcell + 101 + + + + 1 total - + + diff --git a/tests/test_filter_energyfun/inputs_true.dat b/tests/test_filter_energyfun/inputs_true.dat index 48f6c5033..260b28c12 100644 --- a/tests/test_filter_energyfun/inputs_true.dat +++ b/tests/test_filter_energyfun/inputs_true.dat @@ -310,12 +310,16 @@ + + 1e-05 0.369 1000.0 100000.0 600000.0 1000000.0 2000000.0 4000000.0 30000000.0 + 0.1 0.1 0.1333 0.158 0.18467 0.25618 0.4297 0.48 0.48 + Am241 (n,gamma) - + 10000 Am241 (n,gamma) diff --git a/tests/test_filter_mesh/inputs_true.dat b/tests/test_filter_mesh/inputs_true.dat index 1d9d6ac5c..9c196e404 100644 --- a/tests/test_filter_mesh/inputs_true.dat +++ b/tests/test_filter_mesh/inputs_true.dat @@ -327,28 +327,37 @@ -182.07 -182.07 -183.0 182.07 182.07 183.0 + + 1 + + + 2 + + + 3 + - + 10000 total - + 10000 current - + 10001 total - + 10001 current - + 10002 total - + 10002 current diff --git a/tests/test_mg_tallies/inputs_true.dat b/tests/test_mg_tallies/inputs_true.dat index 8120c8681..6d4458444 100644 --- a/tests/test_mg_tallies/inputs_true.dat +++ b/tests/test_mg_tallies/inputs_true.dat @@ -102,129 +102,127 @@ 0.0 0.0 0.0 10 10 5 + + 1 + + + 10000 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 10011 + + + 0.0 20000000.0 + + + 0.0 20000000.0 + + + 1e-05 0.0635 10.0 100.0 1000.0 500000.0 1000000.0 20000000.0 + + + 1e-05 0.0635 10.0 100.0 1000.0 500000.0 1000000.0 20000000.0 + - + 10004 total absorption flux fission nu-fission analog - + 10004 total absorption flux fission nu-fission tracklength - - + 10005 10000 total absorption flux fission nu-fission scatter nu-scatter analog - - + 10005 10000 total absorption flux fission nu-fission collision - - + 10005 10000 total absorption flux fission nu-fission tracklength - - - + 10005 10000 10001 scatter nu-scatter nu-fission - - + 10005 10002 total absorption flux fission nu-fission scatter nu-scatter analog - - + 10005 10002 total absorption flux fission nu-fission collision - - + 10005 10002 total absorption flux fission nu-fission tracklength - - - + 10005 10002 10003 scatter nu-scatter nu-fission - + 10004 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu total absorption fission nu-fission analog - + 10004 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu total absorption fission nu-fission tracklength - - + 10005 10000 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu total absorption fission nu-fission scatter nu-scatter analog - - + 10005 10000 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu total absorption fission nu-fission collision - - + 10005 10000 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu total absorption fission nu-fission tracklength - - - + 10005 10000 10001 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu scatter nu-scatter nu-fission - - + 10005 10002 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu total absorption fission nu-fission scatter nu-scatter analog - - + 10005 10002 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu total absorption fission nu-fission collision - - + 10005 10002 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu total absorption fission nu-fission tracklength - - - + 10005 10002 10003 uo2_ang uo2_ang_mu uo2_iso uo2_iso_mu clad_ang clad_ang_mu clad_iso clad_iso_mu lwtr_ang lwtr_ang_mu lwtr_iso lwtr_iso_mu scatter nu-scatter nu-fission diff --git a/tests/test_mgxs_library_ce_to_mg/inputs_true.dat b/tests/test_mgxs_library_ce_to_mg/inputs_true.dat index e31ee4d04..a70e5c533 100644 --- a/tests/test_mgxs_library_ce_to_mg/inputs_true.dat +++ b/tests/test_mgxs_library_ce_to_mg/inputs_true.dat @@ -50,224 +50,197 @@ + + 10000 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 10001 + + + 10002 + - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total flux analog - - - + 10000 10001 10006 total nu-fission analog - - + 10000 10001 total flux analog - - - + 10000 10001 10006 total nu-scatter-P3 analog - - - + 10000 10001 10006 total nu-scatter analog - - - + 10000 10001 10006 total scatter analog - - + 10013 10001 total flux tracklength - - + 10013 10001 total total tracklength - - + 10013 10001 total flux tracklength - - + 10013 10001 total absorption tracklength - - + 10013 10001 total flux analog - - - + 10013 10001 10006 total nu-fission analog - - + 10013 10001 total flux analog - - - + 10013 10001 10006 total nu-scatter-P3 analog - - - + 10013 10001 10006 total nu-scatter analog - - - + 10013 10001 10006 total scatter analog - - + 10026 10001 total flux tracklength - - + 10026 10001 total total tracklength - - + 10026 10001 total flux tracklength - - + 10026 10001 total absorption tracklength - - + 10026 10001 total flux analog - - - + 10026 10001 10006 total nu-fission analog - - + 10026 10001 total flux analog - - - + 10026 10001 10006 total nu-scatter-P3 analog - - - + 10026 10001 10006 total nu-scatter analog - - - + 10026 10001 10006 total scatter analog diff --git a/tests/test_mgxs_library_condense/inputs_true.dat b/tests/test_mgxs_library_condense/inputs_true.dat index 79c7ea049..bf8caf6d7 100644 --- a/tests/test_mgxs_library_condense/inputs_true.dat +++ b/tests/test_mgxs_library_condense/inputs_true.dat @@ -50,1361 +50,1139 @@ + + 10000 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 0.0 20000000.0 + + + 1 2 3 4 5 6 + + + 10001 + + + 10002 + - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total nu-scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total nu-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total kappa-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - + 10000 10001 total flux analog - - + 10000 10001 total nu-scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-fission analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter-0 analog - - - + 10000 10001 10004 total scatter-0 analog - - + 10000 10045 total nu-fission analog - - + 10000 10004 total nu-fission analog - - + 10000 10045 total prompt-nu-fission analog - - + 10000 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total inverse-velocity tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total prompt-nu-fission tracklength - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10045 total delayed-nu-fission analog - - - + 10000 10058 10004 total delayed-nu-fission analog - - + 10000 10001 total nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total decay-rate tracklength - - + 10000 10001 total flux analog - - - - + 10000 10058 10001 10004 total delayed-nu-fission analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total total tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total total tracklength - - + 10073 10001 total flux analog - - + 10073 10004 total scatter-1 analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total total tracklength - - + 10073 10001 total flux analog - - + 10073 10004 total nu-scatter-1 analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total absorption tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total absorption tracklength - - + 10073 10001 total fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total nu-fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total kappa-fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total scatter tracklength - - + 10073 10001 total flux analog - - + 10073 10001 total nu-scatter analog - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total scatter-P3 analog - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total nu-scatter-P3 analog - - - + 10073 10001 10004 total nu-scatter analog - - - + 10073 10001 10004 total scatter analog - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total nu-fission analog - - - + 10073 10001 10004 total scatter analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total scatter tracklength - - - + 10073 10001 10004 total scatter-P3 analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total scatter tracklength - - - + 10073 10001 10004 total scatter-P3 analog - - - + 10073 10001 10004 total nu-scatter-0 analog - - - + 10073 10001 10004 total scatter-0 analog - - + 10073 10045 total nu-fission analog - - + 10073 10004 total nu-fission analog - - + 10073 10045 total prompt-nu-fission analog - - + 10073 10004 total prompt-nu-fission analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total inverse-velocity tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total prompt-nu-fission tracklength - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total prompt-nu-fission analog - - + 10073 10001 total flux tracklength - - - + 10073 10058 10001 total delayed-nu-fission tracklength - - - + 10073 10058 10045 total delayed-nu-fission analog - - - + 10073 10058 10004 total delayed-nu-fission analog - - + 10073 10001 total nu-fission tracklength - - - + 10073 10058 10001 total delayed-nu-fission tracklength - - - + 10073 10058 10001 total delayed-nu-fission tracklength - - - + 10073 10058 10001 total decay-rate tracklength - - + 10073 10001 total flux analog - - - - + 10073 10058 10001 10004 total delayed-nu-fission analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total total tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total total tracklength - - + 10146 10001 total flux analog - - + 10146 10004 total scatter-1 analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total total tracklength - - + 10146 10001 total flux analog - - + 10146 10004 total nu-scatter-1 analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total absorption tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total absorption tracklength - - + 10146 10001 total fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total nu-fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total kappa-fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total scatter tracklength - - + 10146 10001 total flux analog - - + 10146 10001 total nu-scatter analog - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total scatter-P3 analog - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total nu-scatter-P3 analog - - - + 10146 10001 10004 total nu-scatter analog - - - + 10146 10001 10004 total scatter analog - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total nu-fission analog - - - + 10146 10001 10004 total scatter analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total scatter tracklength - - - + 10146 10001 10004 total scatter-P3 analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total scatter tracklength - - - + 10146 10001 10004 total scatter-P3 analog - - - + 10146 10001 10004 total nu-scatter-0 analog - - - + 10146 10001 10004 total scatter-0 analog - - + 10146 10045 total nu-fission analog - - + 10146 10004 total nu-fission analog - - + 10146 10045 total prompt-nu-fission analog - - + 10146 10004 total prompt-nu-fission analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total inverse-velocity tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total prompt-nu-fission tracklength - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total prompt-nu-fission analog - - + 10146 10001 total flux tracklength - - - + 10146 10058 10001 total delayed-nu-fission tracklength - - - + 10146 10058 10045 total delayed-nu-fission analog - - - + 10146 10058 10004 total delayed-nu-fission analog - - + 10146 10001 total nu-fission tracklength - - - + 10146 10058 10001 total delayed-nu-fission tracklength - - - + 10146 10058 10001 total delayed-nu-fission tracklength - - - + 10146 10058 10001 total decay-rate tracklength - - + 10146 10001 total flux analog - - - - + 10146 10058 10001 10004 total delayed-nu-fission analog diff --git a/tests/test_mgxs_library_distribcell/inputs_true.dat b/tests/test_mgxs_library_distribcell/inputs_true.dat index 79862b8bc..e51dc3405 100644 --- a/tests/test_mgxs_library_distribcell/inputs_true.dat +++ b/tests/test_mgxs_library_distribcell/inputs_true.dat @@ -77,455 +77,386 @@ + + 10000 + + + 0.0 20000000.0 + + + 0.0 20000000.0 + + + 1 2 3 4 5 6 + - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total nu-scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total nu-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total kappa-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - + 10000 10001 total flux analog - - + 10000 10001 total nu-scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-fission analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter-0 analog - - - + 10000 10001 10004 total scatter-0 analog - - + 10000 10001 total nu-fission analog - - + 10000 10004 total nu-fission analog - - + 10000 10001 total prompt-nu-fission analog - - + 10000 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total inverse-velocity tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total prompt-nu-fission tracklength - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission analog - - - + 10000 10058 10004 total delayed-nu-fission analog - - + 10000 10001 total nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total decay-rate tracklength - - + 10000 10001 total flux analog - - - - + 10000 10058 10001 10004 total delayed-nu-fission analog diff --git a/tests/test_mgxs_library_hdf5/inputs_true.dat b/tests/test_mgxs_library_hdf5/inputs_true.dat index 79c7ea049..bf8caf6d7 100644 --- a/tests/test_mgxs_library_hdf5/inputs_true.dat +++ b/tests/test_mgxs_library_hdf5/inputs_true.dat @@ -50,1361 +50,1139 @@ + + 10000 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 0.0 20000000.0 + + + 1 2 3 4 5 6 + + + 10001 + + + 10002 + - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total nu-scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total nu-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total kappa-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - + 10000 10001 total flux analog - - + 10000 10001 total nu-scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-fission analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter-0 analog - - - + 10000 10001 10004 total scatter-0 analog - - + 10000 10045 total nu-fission analog - - + 10000 10004 total nu-fission analog - - + 10000 10045 total prompt-nu-fission analog - - + 10000 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total inverse-velocity tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total prompt-nu-fission tracklength - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10045 total delayed-nu-fission analog - - - + 10000 10058 10004 total delayed-nu-fission analog - - + 10000 10001 total nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total decay-rate tracklength - - + 10000 10001 total flux analog - - - - + 10000 10058 10001 10004 total delayed-nu-fission analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total total tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total total tracklength - - + 10073 10001 total flux analog - - + 10073 10004 total scatter-1 analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total total tracklength - - + 10073 10001 total flux analog - - + 10073 10004 total nu-scatter-1 analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total absorption tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total absorption tracklength - - + 10073 10001 total fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total nu-fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total kappa-fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total scatter tracklength - - + 10073 10001 total flux analog - - + 10073 10001 total nu-scatter analog - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total scatter-P3 analog - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total nu-scatter-P3 analog - - - + 10073 10001 10004 total nu-scatter analog - - - + 10073 10001 10004 total scatter analog - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total nu-fission analog - - - + 10073 10001 10004 total scatter analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total scatter tracklength - - - + 10073 10001 10004 total scatter-P3 analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total scatter tracklength - - - + 10073 10001 10004 total scatter-P3 analog - - - + 10073 10001 10004 total nu-scatter-0 analog - - - + 10073 10001 10004 total scatter-0 analog - - + 10073 10045 total nu-fission analog - - + 10073 10004 total nu-fission analog - - + 10073 10045 total prompt-nu-fission analog - - + 10073 10004 total prompt-nu-fission analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total inverse-velocity tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total prompt-nu-fission tracklength - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total prompt-nu-fission analog - - + 10073 10001 total flux tracklength - - - + 10073 10058 10001 total delayed-nu-fission tracklength - - - + 10073 10058 10045 total delayed-nu-fission analog - - - + 10073 10058 10004 total delayed-nu-fission analog - - + 10073 10001 total nu-fission tracklength - - - + 10073 10058 10001 total delayed-nu-fission tracklength - - - + 10073 10058 10001 total delayed-nu-fission tracklength - - - + 10073 10058 10001 total decay-rate tracklength - - + 10073 10001 total flux analog - - - - + 10073 10058 10001 10004 total delayed-nu-fission analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total total tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total total tracklength - - + 10146 10001 total flux analog - - + 10146 10004 total scatter-1 analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total total tracklength - - + 10146 10001 total flux analog - - + 10146 10004 total nu-scatter-1 analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total absorption tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total absorption tracklength - - + 10146 10001 total fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total nu-fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total kappa-fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total scatter tracklength - - + 10146 10001 total flux analog - - + 10146 10001 total nu-scatter analog - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total scatter-P3 analog - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total nu-scatter-P3 analog - - - + 10146 10001 10004 total nu-scatter analog - - - + 10146 10001 10004 total scatter analog - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total nu-fission analog - - - + 10146 10001 10004 total scatter analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total scatter tracklength - - - + 10146 10001 10004 total scatter-P3 analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total scatter tracklength - - - + 10146 10001 10004 total scatter-P3 analog - - - + 10146 10001 10004 total nu-scatter-0 analog - - - + 10146 10001 10004 total scatter-0 analog - - + 10146 10045 total nu-fission analog - - + 10146 10004 total nu-fission analog - - + 10146 10045 total prompt-nu-fission analog - - + 10146 10004 total prompt-nu-fission analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total inverse-velocity tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total prompt-nu-fission tracklength - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total prompt-nu-fission analog - - + 10146 10001 total flux tracklength - - - + 10146 10058 10001 total delayed-nu-fission tracklength - - - + 10146 10058 10045 total delayed-nu-fission analog - - - + 10146 10058 10004 total delayed-nu-fission analog - - + 10146 10001 total nu-fission tracklength - - - + 10146 10058 10001 total delayed-nu-fission tracklength - - - + 10146 10058 10001 total delayed-nu-fission tracklength - - - + 10146 10058 10001 total decay-rate tracklength - - + 10146 10001 total flux analog - - - - + 10146 10058 10001 10004 total delayed-nu-fission analog diff --git a/tests/test_mgxs_library_mesh/inputs_true.dat b/tests/test_mgxs_library_mesh/inputs_true.dat index b0db8a9c4..9d65a9807 100644 --- a/tests/test_mgxs_library_mesh/inputs_true.dat +++ b/tests/test_mgxs_library_mesh/inputs_true.dat @@ -314,455 +314,386 @@ -100.0 -100.0 100.0 100.0 + + 1 + + + 0.0 20000000.0 + + + 0.0 20000000.0 + + + 1 2 3 4 5 6 + - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total nu-scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total nu-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total kappa-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - + 10000 10001 total flux analog - - + 10000 10001 total nu-scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-fission analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter-0 analog - - - + 10000 10001 10004 total scatter-0 analog - - + 10000 10001 total nu-fission analog - - + 10000 10004 total nu-fission analog - - + 10000 10001 total prompt-nu-fission analog - - + 10000 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total inverse-velocity tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total prompt-nu-fission tracklength - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission analog - - - + 10000 10058 10004 total delayed-nu-fission analog - - + 10000 10001 total nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total decay-rate tracklength - - + 10000 10001 total flux analog - - - - + 10000 10058 10001 10004 total delayed-nu-fission analog diff --git a/tests/test_mgxs_library_no_nuclides/inputs_true.dat b/tests/test_mgxs_library_no_nuclides/inputs_true.dat index 79c7ea049..bf8caf6d7 100644 --- a/tests/test_mgxs_library_no_nuclides/inputs_true.dat +++ b/tests/test_mgxs_library_no_nuclides/inputs_true.dat @@ -50,1361 +50,1139 @@ + + 10000 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 0.0 20000000.0 + + + 1 2 3 4 5 6 + + + 10001 + + + 10002 + - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 total nu-scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total absorption tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total nu-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total kappa-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - + 10000 10001 total flux analog - - + 10000 10001 total nu-scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total nu-fission analog - - - + 10000 10001 10004 total scatter analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total scatter tracklength - - - + 10000 10001 10004 total scatter-P3 analog - - - + 10000 10001 10004 total nu-scatter-0 analog - - - + 10000 10001 10004 total scatter-0 analog - - + 10000 10045 total nu-fission analog - - + 10000 10004 total nu-fission analog - - + 10000 10045 total prompt-nu-fission analog - - + 10000 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - + 10000 10001 total inverse-velocity tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 total prompt-nu-fission tracklength - - + 10000 10001 total flux analog - - - + 10000 10001 10004 total prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10045 total delayed-nu-fission analog - - - + 10000 10058 10004 total delayed-nu-fission analog - - + 10000 10001 total nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total delayed-nu-fission tracklength - - - + 10000 10058 10001 total decay-rate tracklength - - + 10000 10001 total flux analog - - - - + 10000 10058 10001 10004 total delayed-nu-fission analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total total tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total total tracklength - - + 10073 10001 total flux analog - - + 10073 10004 total scatter-1 analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total total tracklength - - + 10073 10001 total flux analog - - + 10073 10004 total nu-scatter-1 analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total absorption tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total absorption tracklength - - + 10073 10001 total fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total nu-fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total kappa-fission tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total scatter tracklength - - + 10073 10001 total flux analog - - + 10073 10001 total nu-scatter analog - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total scatter-P3 analog - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total nu-scatter-P3 analog - - - + 10073 10001 10004 total nu-scatter analog - - - + 10073 10001 10004 total scatter analog - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total nu-fission analog - - - + 10073 10001 10004 total scatter analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total scatter tracklength - - - + 10073 10001 10004 total scatter-P3 analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total scatter tracklength - - - + 10073 10001 10004 total scatter-P3 analog - - - + 10073 10001 10004 total nu-scatter-0 analog - - - + 10073 10001 10004 total scatter-0 analog - - + 10073 10045 total nu-fission analog - - + 10073 10004 total nu-fission analog - - + 10073 10045 total prompt-nu-fission analog - - + 10073 10004 total prompt-nu-fission analog - - + 10073 10001 total flux tracklength - - + 10073 10001 total inverse-velocity tracklength - - + 10073 10001 total flux tracklength - - + 10073 10001 total prompt-nu-fission tracklength - - + 10073 10001 total flux analog - - - + 10073 10001 10004 total prompt-nu-fission analog - - + 10073 10001 total flux tracklength - - - + 10073 10058 10001 total delayed-nu-fission tracklength - - - + 10073 10058 10045 total delayed-nu-fission analog - - - + 10073 10058 10004 total delayed-nu-fission analog - - + 10073 10001 total nu-fission tracklength - - - + 10073 10058 10001 total delayed-nu-fission tracklength - - - + 10073 10058 10001 total delayed-nu-fission tracklength - - - + 10073 10058 10001 total decay-rate tracklength - - + 10073 10001 total flux analog - - - - + 10073 10058 10001 10004 total delayed-nu-fission analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total total tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total total tracklength - - + 10146 10001 total flux analog - - + 10146 10004 total scatter-1 analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total total tracklength - - + 10146 10001 total flux analog - - + 10146 10004 total nu-scatter-1 analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total absorption tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total absorption tracklength - - + 10146 10001 total fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total nu-fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total kappa-fission tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total scatter tracklength - - + 10146 10001 total flux analog - - + 10146 10001 total nu-scatter analog - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total scatter-P3 analog - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total nu-scatter-P3 analog - - - + 10146 10001 10004 total nu-scatter analog - - - + 10146 10001 10004 total scatter analog - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total nu-fission analog - - - + 10146 10001 10004 total scatter analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total scatter tracklength - - - + 10146 10001 10004 total scatter-P3 analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total scatter tracklength - - - + 10146 10001 10004 total scatter-P3 analog - - - + 10146 10001 10004 total nu-scatter-0 analog - - - + 10146 10001 10004 total scatter-0 analog - - + 10146 10045 total nu-fission analog - - + 10146 10004 total nu-fission analog - - + 10146 10045 total prompt-nu-fission analog - - + 10146 10004 total prompt-nu-fission analog - - + 10146 10001 total flux tracklength - - + 10146 10001 total inverse-velocity tracklength - - + 10146 10001 total flux tracklength - - + 10146 10001 total prompt-nu-fission tracklength - - + 10146 10001 total flux analog - - - + 10146 10001 10004 total prompt-nu-fission analog - - + 10146 10001 total flux tracklength - - - + 10146 10058 10001 total delayed-nu-fission tracklength - - - + 10146 10058 10045 total delayed-nu-fission analog - - - + 10146 10058 10004 total delayed-nu-fission analog - - + 10146 10001 total nu-fission tracklength - - - + 10146 10058 10001 total delayed-nu-fission tracklength - - - + 10146 10058 10001 total delayed-nu-fission tracklength - - - + 10146 10058 10001 total decay-rate tracklength - - + 10146 10001 total flux analog - - - - + 10146 10058 10001 10004 total delayed-nu-fission analog diff --git a/tests/test_mgxs_library_nuclides/inputs_true.dat b/tests/test_mgxs_library_nuclides/inputs_true.dat index 89541b4d5..7a16a9afa 100644 --- a/tests/test_mgxs_library_nuclides/inputs_true.dat +++ b/tests/test_mgxs_library_nuclides/inputs_true.dat @@ -50,1127 +50,956 @@ + + 10000 + + + 0.0 0.625 20000000.0 + + + 0.0 0.625 20000000.0 + + + 0.0 20000000.0 + + + 10001 + + + 10002 + - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 total tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 U234 U235 U238 O16 scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 total tracklength - - + 10000 10001 total flux analog - - + 10000 10004 U234 U235 U238 O16 nu-scatter-1 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 absorption tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 absorption tracklength - - + 10000 10001 U234 U235 U238 O16 fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 nu-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 kappa-fission tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 scatter tracklength - - + 10000 10001 total flux analog - - + 10000 10001 U234 U235 U238 O16 nu-scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 U234 U235 U238 O16 scatter-P3 analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 U234 U235 U238 O16 nu-scatter-P3 analog - - - + 10000 10001 10004 U234 U235 U238 O16 nu-scatter analog - - - + 10000 10001 10004 U234 U235 U238 O16 scatter analog - - + 10000 10001 total flux analog - - - + 10000 10001 10004 U234 U235 U238 O16 nu-fission analog - - - + 10000 10001 10004 U234 U235 U238 O16 scatter analog - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 scatter tracklength - - - + 10000 10001 10004 U234 U235 U238 O16 scatter-P3 analog - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 scatter tracklength - - - + 10000 10001 10004 U234 U235 U238 O16 scatter-P3 analog - - - + 10000 10001 10004 U234 U235 U238 O16 nu-scatter-0 analog - - - + 10000 10001 10004 U234 U235 U238 O16 scatter-0 analog - - + 10000 10045 U234 U235 U238 O16 nu-fission analog - - + 10000 10004 U234 U235 U238 O16 nu-fission analog - - + 10000 10045 U234 U235 U238 O16 prompt-nu-fission analog - - + 10000 10004 U234 U235 U238 O16 prompt-nu-fission analog - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 inverse-velocity tracklength - - + 10000 10001 total flux tracklength - - + 10000 10001 U234 U235 U238 O16 prompt-nu-fission tracklength - - + 10000 10001 total flux analog - - - + 10000 10001 10004 U234 U235 U238 O16 prompt-nu-fission analog - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 total tracklength - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 total tracklength - - + 10056 10001 total flux analog - - + 10056 10004 Zr90 Zr91 Zr92 Zr94 Zr96 scatter-1 analog - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 total tracklength - - + 10056 10001 total flux analog - - + 10056 10004 Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter-1 analog - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 absorption tracklength - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 absorption tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 fission tracklength - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 fission tracklength - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 nu-fission tracklength - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 kappa-fission tracklength - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 scatter tracklength - - + 10056 10001 total flux analog - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter analog - - + 10056 10001 total flux analog - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 scatter-P3 analog - - + 10056 10001 total flux analog - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter-P3 analog - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter analog - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 scatter analog - - + 10056 10001 total flux analog - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 nu-fission analog - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 scatter analog - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 scatter tracklength - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 scatter-P3 analog - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 scatter tracklength - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 scatter-P3 analog - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter-0 analog - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 scatter-0 analog - - + 10056 10045 Zr90 Zr91 Zr92 Zr94 Zr96 nu-fission analog - - + 10056 10004 Zr90 Zr91 Zr92 Zr94 Zr96 nu-fission analog - - + 10056 10045 Zr90 Zr91 Zr92 Zr94 Zr96 prompt-nu-fission analog - - + 10056 10004 Zr90 Zr91 Zr92 Zr94 Zr96 prompt-nu-fission analog - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 inverse-velocity tracklength - - + 10056 10001 total flux tracklength - - + 10056 10001 Zr90 Zr91 Zr92 Zr94 Zr96 prompt-nu-fission tracklength - - + 10056 10001 total flux analog - - - + 10056 10001 10004 Zr90 Zr91 Zr92 Zr94 Zr96 prompt-nu-fission analog - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 total tracklength - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 total tracklength - - + 10112 10001 total flux analog - - + 10112 10004 H1 O16 B10 B11 scatter-1 analog - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 total tracklength - - + 10112 10001 total flux analog - - + 10112 10004 H1 O16 B10 B11 nu-scatter-1 analog - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 absorption tracklength - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 absorption tracklength - - + 10112 10001 H1 O16 B10 B11 fission tracklength - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 fission tracklength - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 nu-fission tracklength - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 kappa-fission tracklength - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 scatter tracklength - - + 10112 10001 total flux analog - - + 10112 10001 H1 O16 B10 B11 nu-scatter analog - - + 10112 10001 total flux analog - - - + 10112 10001 10004 H1 O16 B10 B11 scatter-P3 analog - - + 10112 10001 total flux analog - - - + 10112 10001 10004 H1 O16 B10 B11 nu-scatter-P3 analog - - - + 10112 10001 10004 H1 O16 B10 B11 nu-scatter analog - - - + 10112 10001 10004 H1 O16 B10 B11 scatter analog - - + 10112 10001 total flux analog - - - + 10112 10001 10004 H1 O16 B10 B11 nu-fission analog - - - + 10112 10001 10004 H1 O16 B10 B11 scatter analog - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 scatter tracklength - - - + 10112 10001 10004 H1 O16 B10 B11 scatter-P3 analog - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 scatter tracklength - - - + 10112 10001 10004 H1 O16 B10 B11 scatter-P3 analog - - - + 10112 10001 10004 H1 O16 B10 B11 nu-scatter-0 analog - - - + 10112 10001 10004 H1 O16 B10 B11 scatter-0 analog - - + 10112 10045 H1 O16 B10 B11 nu-fission analog - - + 10112 10004 H1 O16 B10 B11 nu-fission analog - - + 10112 10045 H1 O16 B10 B11 prompt-nu-fission analog - - + 10112 10004 H1 O16 B10 B11 prompt-nu-fission analog - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 inverse-velocity tracklength - - + 10112 10001 total flux tracklength - - + 10112 10001 H1 O16 B10 B11 prompt-nu-fission tracklength - - + 10112 10001 total flux analog - - - + 10112 10001 10004 H1 O16 B10 B11 prompt-nu-fission analog diff --git a/tests/test_score_current/tallies.xml b/tests/test_score_current/tallies.xml index 5da08ef9d..3b8f60adb 100644 --- a/tests/test_score_current/tallies.xml +++ b/tests/test_score_current/tallies.xml @@ -8,14 +8,23 @@ 17 17 17 + + mesh + 1 + + + + energy + 0. 0.253 20.0e6 + + - + 1 current - - + 1 2 current diff --git a/tests/test_sourcepoint_restart/tallies.xml b/tests/test_sourcepoint_restart/tallies.xml index fd7ee66fb..db9b2ed75 100644 --- a/tests/test_sourcepoint_restart/tallies.xml +++ b/tests/test_sourcepoint_restart/tallies.xml @@ -8,15 +8,33 @@ 10. 4. 9. + + mesh + 1 + + + + energy + 0.0 5.0e6 10.0e6 + + + + energyout + 0.0 5.0e6 10.0e6 + + + + cell + 1 + + - - - + 1 2 3 scatter-P3 nu-fission - + 4 fission absorption total flux diff --git a/tests/test_statepoint_restart/tallies.xml b/tests/test_statepoint_restart/tallies.xml index fd7ee66fb..db9b2ed75 100644 --- a/tests/test_statepoint_restart/tallies.xml +++ b/tests/test_statepoint_restart/tallies.xml @@ -8,15 +8,33 @@ 10. 4. 9. + + mesh + 1 + + + + energy + 0.0 5.0e6 10.0e6 + + + + energyout + 0.0 5.0e6 10.0e6 + + + + cell + 1 + + - - - + 1 2 3 scatter-P3 nu-fission - + 4 fission absorption total flux diff --git a/tests/test_tallies/inputs_true.dat b/tests/test_tallies/inputs_true.dat index 88ff72f9b..5543ea917 100644 --- a/tests/test_tallies/inputs_true.dat +++ b/tests/test_tallies/inputs_true.dat @@ -314,160 +314,192 @@ -182.07 -182.07 182.07 182.07 + + -3.14159 -1.885 -0.6283 0.6283 1.885 3.14159 + + + 1 + + + 10 21 22 23 + + + 1 2 3 4 5 6 + + + 0.0 0.253 1000.0 1000000.0 20000000.0 + + + 0.0 0.253 1000.0 1000000.0 20000000.0 + + + 1 2 3 4 + + + -1.0 -0.5 0.0 0.5 1.0 + + + 0.0 0.6283 1.2566 1.885 2.5132 3.14159 + + + 1 2 3 4 6 8 + + + 10 21 22 23 60 + + + 21 22 23 27 28 29 60 + - + 10000 flux tracklength - + 10000 flux analog - - + 10000 10001 flux tracklength - + 10002 total - + 10003 delayed-nu-fission - + 10004 total - + 10005 scatter - - + 10004 10005 scatter nu-fission - + 10006 total - + 10007 scatter nu-scatter - - + 10007 10001 scatter nu-scatter - + 10008 flux tracklength - + 10008 flux analog - - + 10008 10001 flux tracklength - + 10009 total - + 10010 absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable tracklength - + 10010 absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable analog - + 10010 absorption delayed-nu-fission events fission inverse-velocity kappa-fission (n,2n) (n,n1) (n,gamma) nu-fission scatter elastic total prompt-nu-fission fission-q-prompt fission-q-recoverable collision - + 10011 flux - + 10011 flux-y5 tracklength - + 10011 flux-y5 analog - + 10011 flux-y5 collision - + 10010 scatter scatter-1 scatter-2 scatter-3 scatter-4 nu-scatter nu-scatter-1 nu-scatter-2 nu-scatter-3 nu-scatter-4 - + 10010 scatter-p4 scatter-y4 nu-scatter-p4 nu-scatter-y3 - + 10010 total - + 10010 U235 total total-y4 tracklength - + 10010 U235 total total-y4 analog - + 10010 U235 total total-y4 collision - + 10010 all total tracklength - + 10010 all total collision - + 10001 all total tracklength - + 10001 U235 total tracklength diff --git a/tests/test_tally_aggregation/inputs_true.dat b/tests/test_tally_aggregation/inputs_true.dat index 8223b8d6a..3b7d6a5c6 100644 --- a/tests/test_tally_aggregation/inputs_true.dat +++ b/tests/test_tally_aggregation/inputs_true.dat @@ -312,9 +312,14 @@ + + 0.0 0.253 1000.0 1000000.0 20000000.0 + + + 60 + - - + 10000 10001 U234 U235 U238 nu-fission total diff --git a/tests/test_tally_arithmetic/inputs_true.dat b/tests/test_tally_arithmetic/inputs_true.dat index 4ade94e93..378750355 100644 --- a/tests/test_tally_arithmetic/inputs_true.dat +++ b/tests/test_tally_arithmetic/inputs_true.dat @@ -317,16 +317,25 @@ -160.0 -160.0 -183.0 160.0 160.0 183.0 + + 1 3 + + + 0.0 2.53e-07 0.001 1.0 20.0 + + + 60 + + + 1 + - - - + 10001 10000 10002 U234 U235 nu-fission total - - + 10000 10003 U238 U235 total fission diff --git a/tests/test_tally_assumesep/tallies.xml b/tests/test_tally_assumesep/tallies.xml index 2de171471..c588eb9e4 100644 --- a/tests/test_tally_assumesep/tallies.xml +++ b/tests/test_tally_assumesep/tallies.xml @@ -3,19 +3,34 @@ true + + cell + 21 + + + + cell + 22 + + + + cell + 23 + + - + 1 total - + 2 total - + 3 total - \ No newline at end of file + diff --git a/tests/test_tally_slice_merge/inputs_true.dat b/tests/test_tally_slice_merge/inputs_true.dat index 93b4af5cd..cd48586b5 100644 --- a/tests/test_tally_slice_merge/inputs_true.dat +++ b/tests/test_tally_slice_merge/inputs_true.dat @@ -315,23 +315,32 @@ -50.0 -50.0 50.0 50.0 + + 21 27 + + + 0.0 0.625 20000000.0 + + + 21 + + + 10000 + - - + 10015 10007 U235 U238 fission nu-fission tracklength - - + 10005 10007 U235 U238 fission nu-fission tracklength - - + 10006 10007 U235 U238 fission nu-fission tracklength From 7af1be9302527b714d259f66398feb082fd04833 Mon Sep 17 00:00:00 2001 From: amandalund Date: Thu, 30 Mar 2017 10:50:12 -0500 Subject: [PATCH 10/18] Fix surface and mesh filters for current score --- docs/source/io_formats/statepoint.rst | 3 +- openmc/statepoint.py | 4 +-- src/input_xml.F90 | 41 +++++++++++++++++++---- tests/test_filter_mesh/results_true.dat | 2 +- tests/test_score_current/results_true.dat | 2 +- 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index af6e3a1bc..b0321814f 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -125,7 +125,8 @@ The current version of the statepoint file format is 16.0. :Datasets: - **n_realizations** (*int*) -- Number of realizations. - **n_filters** (*int*) -- Number of filters used. - - **filters** (*int[]*) -- IDs of the filters on the tally + - **filters** (*int[]*) -- User-defined unique IDs of the filters on + the tally - **nuclides** (*char[][]*) -- Array of nuclides to tally. Note that if no nuclide is specified in the user input, a single 'total' nuclide appears here. diff --git a/openmc/statepoint.py b/openmc/statepoint.py index f0085395c..63a78a5a1 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -69,8 +69,8 @@ class StatePoint(object): Cross-product of absorption and tracklength estimates of k-effective k_generation : numpy.ndarray Estimate of k-effective for each batch/generation - MESHES : DICT - DICTIONARY WHOSE KEYS ARE MESH IDS AND WHOSE VALUES ARE MESH OBJECTS + meshes : dict + Dictionary whose keys are mesh IDs and whose values are Mesh objects n_batches : int Number of batches n_inactive : int diff --git a/src/input_xml.F90 b/src/input_xml.F90 index b1c0cc49c..7d577eeff 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2616,6 +2616,7 @@ contains integer :: filter_id ! user-specified identifier for filter integer :: i_mesh ! index in meshes array integer :: i_filt ! index in filters array + integer :: i_filter_mesh ! index of mesh filter integer :: n ! size of arrays in mesh specification integer :: n_words ! number of words read integer :: n_filter ! number of filters @@ -3792,14 +3793,21 @@ contains end if ! Get index of mesh filter - i_filt = t % filter(t % find_filter(FILTER_MESH)) + i_filter_mesh = t % filter(t % find_filter(FILTER_MESH)) ! Check to make sure mesh filter was specified - if (i_filt == 0) then + if (i_filter_mesh == 0) then call fatal_error("Cannot tally surface current without a mesh & &filter.") end if + ! Get pointer to mesh + select type(filt => filters(i_filter_mesh) % obj) + type is (MeshFilter) + i_mesh = filt % mesh + m => meshes(i_mesh) + end select + ! Copy filter indices to temporary array allocate(temp_filter(size(t % filter) + 1)) temp_filter(1:size(t % filter)) = t % filter @@ -3809,14 +3817,35 @@ contains call move_alloc(FROM=temp_filter, TO=t % filter) n_filter = size(t % filter) - ! Extend the filters array so we can add a surface filter - call add_filters(1) + ! Extend the filters array so we can add a surface filter and mesh + ! filter + call add_filters(2) ! Increment number of user filters - n_user_filters = n_user_filters + 1 + n_user_filters = n_user_filters + 2 + + ! Get index of the new mesh filter + i_filt = n_user_filters - 1 + + ! Duplicate the mesh filter since other tallies might use this + ! filter and we need to change the dimension + allocate(MeshFilter :: filters(i_filt) % obj) + select type(filt => filters(i_filt) % obj) + type is (MeshFilter) + filt % id = i_filt + filt % mesh = i_mesh + + ! We need to increase the dimension by one since we also need + ! currents coming into and out of the boundary mesh cells. + filt % n_bins = product(m % dimension + 1) + + ! Add filter to dictionary + call filter_dict % add_key(filt % id, i_filt) + end select + t % filter(t % find_filter(FILTER_MESH)) = i_filt ! Get index of the new surface filter - i_filt = n_filters + i_filt = n_user_filters ! Add surface filter allocate(SurfaceFilter :: filters(i_filt) % obj) diff --git a/tests/test_filter_mesh/results_true.dat b/tests/test_filter_mesh/results_true.dat index 3c25aa738..61ba50e20 100644 --- a/tests/test_filter_mesh/results_true.dat +++ b/tests/test_filter_mesh/results_true.dat @@ -1 +1 @@ -ba64175b12e3b1be70493399f6cca2319947c17e26cf5d1d73398387214b8c18c2cb842c14d838da31a7a1eee18d407b8f7a319d5d2dab6b4a7a7dffa8770f1f \ No newline at end of file +2416e74f84dd57c46a6e2fc94e8f794d9725cae964beaf4659f06aae5ed2b804b968cf2ca512b461d6e59e998f61a967db2f2fe97ce22e7607444f50ca38f646 \ No newline at end of file diff --git a/tests/test_score_current/results_true.dat b/tests/test_score_current/results_true.dat index cb1cebf24..75d61b718 100644 --- a/tests/test_score_current/results_true.dat +++ b/tests/test_score_current/results_true.dat @@ -1 +1 @@ -b08d79380540e6170000f6886a7dc97b9d0c830698ac1c1e009a2c6383d542650d37a0e307a4f82771492f73fcd654f7f5c9d01d28fb3b0e8824678656c63a85 \ No newline at end of file +4675d5101f4f829369c39cb33d654430836b934ab07c165777ba6e214bdf3a698b8082f4f9bb9e78f1f0e495b30ea02cf9b3d14622c59915d818d678a1e5b7b1 \ No newline at end of file From ff6bb88bf5c369764704d1e94f0b4e5b4903c51b Mon Sep 17 00:00:00 2001 From: amandalund Date: Thu, 30 Mar 2017 21:20:01 -0500 Subject: [PATCH 11/18] Change Filter __hash__ to not use user-defined unique ID --- openmc/filter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openmc/filter.py b/openmc/filter.py index 4e1b4ccb9..ddd2e78ba 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -134,7 +134,9 @@ class Filter(object): return not self > other def __hash__(self): - return hash(repr(self)) + string = type(self).__name__ + '\n' + string += '{: <16}=\t{}\n'.format('\tBins', self.bins) + return hash(repr(string)) def __repr__(self): string = type(self).__name__ + '\n' From 2436237ce714e74c5379116a562653d579bcec91 Mon Sep 17 00:00:00 2001 From: amandalund Date: Fri, 31 Mar 2017 15:22:04 -0500 Subject: [PATCH 12/18] Change how check for duplicate filters is done when exporting to tallies.xml file --- openmc/tallies.py | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 7396635d0..6e1f5383a 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3468,20 +3468,6 @@ class Tallies(cv.CheckedList): # Continue iterating from the first loop break - def remove_duplicate_filters(self): - """Search all tallies for any identical filters and set the IDs of - identical filters to the same value. This prevents a filter from being - written multiple times to the tallies.xml input file. - - """ - - for tally1 in self: - for filter1 in tally1.filters: - for tally2 in self: - for filter2 in tally2.filters: - if filter1 == filter2: - filter2.id = filter1.id - def add_mesh(self, mesh): """Add a mesh to the file @@ -3534,12 +3520,16 @@ class Tallies(cv.CheckedList): already_written.add(f.mesh) def _create_filter_subelements(self, root_element): - already_written = set() + already_written = dict() for tally in self: for f in tally.filters: if f not in already_written: root_element.append(f.to_xml_element()) - already_written.add(f) + already_written[f] = f.id + else: + # Set the IDs of identical filters with different + # user-defined IDs to the same value + f.id = already_written[f] def _create_derivative_subelements(self, root_element): # Get a list of all derivatives referenced in a tally. @@ -3553,23 +3543,16 @@ class Tallies(cv.CheckedList): for d in derivs: root_element.append(d.to_xml_element()) - def export_to_xml(self, path='tallies.xml', reduce_filters=True): + def export_to_xml(self, path='tallies.xml'): """Create a tallies.xml file that can be used for a simulation. Parameters ---------- path : str Path to file to write. Defaults to 'tallies.xml'. - reduce_filters : bool - Indicates whether duplicate filters should be removed. This - prevents identical filters with different user IDs from being - written to the tallies.xml input file. Defaults to True. """ - if reduce_filters: - self.remove_duplicate_filters() - root_element = ET.Element("tallies") self._create_mesh_subelements(root_element) self._create_filter_subelements(root_element) From fe1f6062a4a8fe8019f833f06afef2df990ba7d7 Mon Sep 17 00:00:00 2001 From: amandalund Date: Fri, 31 Mar 2017 17:37:09 -0500 Subject: [PATCH 13/18] Switched type of active_*tallies from SetInt to VectorInt to eliminate need for threadprivate --- src/cmfd_input.F90 | 2 -- src/global.F90 | 14 ++++++-------- src/simulation.F90 | 2 -- src/tally.F90 | 44 ++++++++++++++++++++++++++++---------------- 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index 8b67f7a8f..91f2e03b6 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -607,9 +607,7 @@ contains end do ! Put cmfd tallies into active tally array and turn tallies on -!$omp parallel call setup_active_cmfdtallies() -!$omp end parallel tallies_on = .true. end subroutine create_cmfd_tally diff --git a/src/global.F90 b/src/global.F90 index 815063344..dd013b3a8 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -18,6 +18,7 @@ module global use plot_header, only: ObjectPlot use sab_header, only: SAlphaBeta use set_header, only: SetInt + use stl_vector, only: VectorInt use surface_header, only: SurfaceContainer use source_header, only: SourceDistribution use tally_header, only: TallyObject, TallyDerivative @@ -154,14 +155,11 @@ module global integer :: i_cmfd_tallies = -1 ! Active tally lists - type(SetInt) :: active_analog_tallies - type(SetInt) :: active_tracklength_tallies - type(SetInt) :: active_current_tallies - type(SetInt) :: active_collision_tallies - type(SetInt) :: active_tallies -!$omp threadprivate(active_analog_tallies, active_tracklength_tallies, & -!$omp& active_current_tallies, active_collision_tallies, & -!$omp& active_tallies) + type(VectorInt) :: active_analog_tallies + type(VectorInt) :: active_tracklength_tallies + type(VectorInt) :: active_current_tallies + type(VectorInt) :: active_collision_tallies + type(VectorInt) :: active_tallies ! Global tallies ! 1) collision estimate of k-eff diff --git a/src/simulation.F90 b/src/simulation.F90 index 13cc9b669..0cdb4c66d 100644 --- a/src/simulation.F90 +++ b/src/simulation.F90 @@ -186,9 +186,7 @@ contains tallies_on = .true. ! Add user tallies to active tallies list -!$omp parallel call setup_active_usertallies() -!$omp end parallel end if ! check CMFD initialize batch diff --git a/src/tally.F90 b/src/tally.F90 index f222fc55f..02ab07339 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2219,7 +2219,7 @@ contains TALLY_LOOP: do i = 1, active_analog_tallies % size() ! Get index of tally and pointer to tally - i_tally = active_analog_tallies % get_item(i) + i_tally = active_analog_tallies % data(i) t => tallies(i_tally) ! Find the first bin in each filter. There may be more than one matching @@ -2356,7 +2356,7 @@ contains TALLY_LOOP: do i = 1, active_analog_tallies % size() ! Get index of tally and pointer to tally - i_tally = active_analog_tallies % get_item(i) + i_tally = active_analog_tallies % data(i) t => tallies(i_tally) ! Get pointer to current material. We need this in order to determine what @@ -2689,7 +2689,7 @@ contains TALLY_LOOP: do i = 1, active_tracklength_tallies % size() ! Get index of tally and pointer to tally - i_tally = active_tracklength_tallies % get_item(i) + i_tally = active_tracklength_tallies % data(i) t => tallies(i_tally) ! Find the first bin in each filter. There may be more than one matching @@ -2845,7 +2845,7 @@ contains TALLY_LOOP: do i = 1, active_collision_tallies % size() ! Get index of tally and pointer to tally - i_tally = active_collision_tallies % get_item(i) + i_tally = active_collision_tallies % data(i) t => tallies(i_tally) ! Find the first bin in each filter. There may be more than one matching @@ -3004,7 +3004,7 @@ contains xyz1 = p % coord(1) % xyz ! Get pointer to tally - i_tally = active_current_tallies % get_item(i) + i_tally = active_current_tallies % data(i) t => tallies(i_tally) ! Get index for mesh, surface, and energy filters @@ -4025,7 +4025,7 @@ contains if (master .or. (.not. reduce_tallies)) then ! Accumulate results for each tally do i = 1, active_tallies % size() - call accumulate_tally(tallies(active_tallies % get_item(i))) + call accumulate_tally(tallies(active_tallies % data(i))) end do if (run_mode == MODE_EIGENVALUE) then @@ -4070,7 +4070,7 @@ contains type(TallyObject), pointer :: t do i = 1, active_tallies % size() - t => tallies(active_tallies % get_item(i)) + t => tallies(active_tallies % data(i)) m = t % total_score_bins n = t % total_filter_bins @@ -4214,22 +4214,28 @@ contains do i = 1, n_user_tallies ! Add tally to active tallies - call active_tallies % add(i_user_tallies + i) + call active_tallies % push_back(i_user_tallies + i) ! Check what type of tally this is and add it to the appropriate list if (user_tallies(i) % type == TALLY_VOLUME) then if (user_tallies(i) % estimator == ESTIMATOR_ANALOG) then - call active_analog_tallies % add(i_user_tallies + i) + call active_analog_tallies % push_back(i_user_tallies + i) elseif (user_tallies(i) % estimator == ESTIMATOR_TRACKLENGTH) then - call active_tracklength_tallies % add(i_user_tallies + i) + call active_tracklength_tallies % push_back(i_user_tallies + i) elseif (user_tallies(i) % estimator == ESTIMATOR_COLLISION) then - call active_collision_tallies % add(i_user_tallies + i) + call active_collision_tallies % push_back(i_user_tallies + i) end if elseif (user_tallies(i) % type == TALLY_SURFACE_CURRENT) then - call active_current_tallies % add(i_user_tallies + i) + call active_current_tallies % push_back(i_user_tallies + i) end if end do + call active_tallies % shrink_to_fit() + call active_analog_tallies % shrink_to_fit() + call active_tracklength_tallies % shrink_to_fit() + call active_collision_tallies % shrink_to_fit() + call active_current_tallies % shrink_to_fit() + end subroutine setup_active_usertallies !=============================================================================== @@ -4256,20 +4262,26 @@ contains do i = 1, n_cmfd_tallies ! Add CMFD tally to active tallies - call active_tallies % add(i_cmfd_tallies + i) + call active_tallies % push_back(i_cmfd_tallies + i) ! Check what type of tally this is and add it to the appropriate list if (cmfd_tallies(i) % type == TALLY_VOLUME) then if (cmfd_tallies(i) % estimator == ESTIMATOR_ANALOG) then - call active_analog_tallies % add(i_cmfd_tallies + i) + call active_analog_tallies % push_back(i_cmfd_tallies + i) elseif (cmfd_tallies(i) % estimator == ESTIMATOR_TRACKLENGTH) then - call active_tracklength_tallies % add(i_cmfd_tallies + i) + call active_tracklength_tallies % push_back(i_cmfd_tallies + i) end if elseif (cmfd_tallies(i) % type == TALLY_SURFACE_CURRENT) then - call active_current_tallies % add(i_cmfd_tallies + i) + call active_current_tallies % push_back(i_cmfd_tallies + i) end if end do + call active_tallies % shrink_to_fit() + call active_analog_tallies % shrink_to_fit() + call active_tracklength_tallies % shrink_to_fit() + call active_collision_tallies % shrink_to_fit() + call active_current_tallies % shrink_to_fit() + end subroutine setup_active_cmfdtallies end module tally From 1f750bfaceb59ef4ce28d7b0331d04402521bbfb Mon Sep 17 00:00:00 2001 From: amandalund Date: Wed, 5 Apr 2017 20:39:12 -0500 Subject: [PATCH 14/18] Restructed tally score loop; replaced matching_bins with and filter_weights with new TallyFilterMatch array --- src/cmfd_data.F90 | 179 +++++--- src/global.F90 | 11 +- src/initialize.F90 | 2 +- src/output.F90 | 165 ++++--- src/tally.F90 | 525 +++++++++++++++-------- src/tally_filter_header.F90 | 14 + src/tally_initialize.F90 | 10 +- src/trigger.F90 | 77 ++-- tests/test_diff_tally/test_diff_tally.py | 1 - 9 files changed, 642 insertions(+), 342 deletions(-) diff --git a/src/cmfd_data.F90 b/src/cmfd_data.F90 index a2a642fc7..2e304a909 100644 --- a/src/cmfd_data.F90 +++ b/src/cmfd_data.F90 @@ -57,7 +57,7 @@ contains ZERO, ONE, TINY_BIT use error, only: fatal_error use global, only: cmfd, n_cmfd_tallies, cmfd_tallies, meshes, & - filters, matching_bins + filters, filter_matches use mesh, only: mesh_indices_to_bin use mesh_header, only: RegularMesh use string, only: to_str @@ -72,6 +72,7 @@ contains integer :: k ! iteration counter for z integer :: g ! iteration counter for g integer :: h ! iteration counter for outgoing groups + integer :: l ! iteration counter for tally filters integer :: ital ! tally object index integer :: ijk(3) ! indices for mesh cell integer :: score_index ! index to pull from tally object @@ -81,6 +82,7 @@ contains integer :: i_filter_ein ! index for incoming energy filter integer :: i_filter_eout ! index for outgoing energy filter integer :: i_filter_surf ! index for surface filter + logical :: energy_filters! energy filters present real(8) :: flux ! temp variable for flux type(TallyObject), pointer :: t ! pointer for tally object type(RegularMesh), pointer :: m ! pointer for mesh object @@ -123,10 +125,14 @@ contains end select m => meshes(i_mesh) - i_filter_mesh = t % find_filter(FILTER_MESH) - i_filter_ein = t % find_filter(FILTER_ENERGYIN) - i_filter_eout = t % find_filter(FILTER_ENERGYOUT) - i_filter_surf = t % find_filter(FILTER_SURFACE) + ! Check for energy filters + energy_filters = (t % find_filter(FILTER_ENERGYIN) > 0) + + i_filter_mesh = t % filter(t % find_filter(FILTER_MESH)) + if (energy_filters) then + i_filter_ein = t % filter(t % find_filter(FILTER_ENERGYIN)) + i_filter_eout = t % filter(t % find_filter(FILTER_ENERGYOUT)) + end if ! Begin loop around space ZLOOP: do k = 1,nz @@ -149,22 +155,29 @@ contains TALLY: if (ital == 1) then ! Reset all bins to 1 - matching_bins(1:size(t % filter)) = 1 + do l = 1, size(t % filter) + call filter_matches(t % filter(l)) % bins % clear() + call filter_matches(t % filter(l)) % bins % push_back(1) + end do ! Set ijk as mesh indices ijk = (/ i, j, k /) ! Get bin number for mesh indices - matching_bins(i_filter_mesh) = mesh_indices_to_bin(m,ijk) + filter_matches(i_filter_mesh) % bins % data(1) = & + mesh_indices_to_bin(m,ijk) ! Apply energy in filter - if (i_filter_ein > 0) then - matching_bins(i_filter_ein) = ng - h + 1 + if (energy_filters) then + filter_matches(i_filter_ein) % bins % data(1) = ng - h + 1 end if ! Calculate score index from bins - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t%stride) + 1 + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do ! Get flux flux = t % results(RESULT_SUM,1,score_index) @@ -193,25 +206,32 @@ contains INGROUP: do g = 1, ng ! Reset all bins to 1 - matching_bins(1:size(t % filter)) = 1 + do l = 1, size(t % filter) + call filter_matches(t % filter(l)) % bins % clear() + call filter_matches(t % filter(l)) % bins % push_back(1) + end do ! Set ijk as mesh indices ijk = (/ i, j, k /) ! Get bin number for mesh indices - matching_bins(i_filter_mesh) = mesh_indices_to_bin(m,ijk) + filter_matches(i_filter_mesh) % bins % data(1) = & + mesh_indices_to_bin(m,ijk) - if (i_filter_ein > 0) then + if (energy_filters) then ! Apply energy in filter - matching_bins(i_filter_ein) = ng - h + 1 + filter_matches(i_filter_ein) % bins % data(1) = ng - h + 1 ! Set energy out bin - matching_bins(i_filter_eout) = ng - g + 1 + filter_matches(i_filter_eout) % bins % data(1) = ng - g + 1 end if ! Calculate score index from bins - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t%stride) + 1 + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do ! Get scattering cmfd % scattxs(h,g,i,j,k) = t % results(RESULT_SUM,1,score_index) /& @@ -231,80 +251,121 @@ contains else if (ital == 3) then + i_filter_surf = t % filter(t % find_filter(FILTER_SURFACE)) + ! Initialize and filter for energy - matching_bins(1:size(t % filter)) = 1 - if (i_filter_ein > 0) then - matching_bins(i_filter_ein) = ng - h + 1 + do l = 1, size(t % filter) + call filter_matches(t % filter(l)) % bins % clear() + call filter_matches(t % filter(l)) % bins % push_back(1) + end do + if (energy_filters) then + filter_matches(i_filter_ein) % bins % data(1) = ng - h + 1 end if ! Get the bin for this mesh cell - matching_bins(i_filter_mesh) = mesh_indices_to_bin(m, & - (/ i, j, k /)) + filter_matches(i_filter_mesh) % bins % data(1) = & + mesh_indices_to_bin(m, (/ i, j, k /)) ! Left surface - matching_bins(i_filter_surf) = OUT_LEFT - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_LEFT + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(1,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - matching_bins(i_filter_surf) = IN_LEFT - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_LEFT + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(2,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Right surface - matching_bins(i_filter_surf) = IN_RIGHT - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_RIGHT + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(3,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - matching_bins(i_filter_surf) = OUT_RIGHT - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_RIGHT + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(4,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Back surface - matching_bins(i_filter_surf) = OUT_BACK - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_BACK + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(5,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - matching_bins(i_filter_surf) = IN_BACK - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_BACK + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(6,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Front surface - matching_bins(i_filter_surf) = IN_FRONT - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_FRONT + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(7,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - matching_bins(i_filter_surf) = OUT_FRONT - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_FRONT + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(8,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Bottom surface - matching_bins(i_filter_surf) = OUT_BOTTOM - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_BOTTOM + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(9,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - matching_bins(i_filter_surf) = IN_BOTTOM - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_BOTTOM + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(10,h,i,j,k) = t % results(RESULT_SUM,1,score_index) ! Top surface - matching_bins(i_filter_surf) = IN_TOP - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_TOP + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(11,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - matching_bins(i_filter_surf) = OUT_TOP - score_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_TOP + score_index = 1 + do l = 1, size(t % filter) + score_index = score_index + (filter_matches(t % filter(l)) & + % bins % data(1) - 1) * t % stride(l) + end do cmfd % current(12,h,i,j,k) = t % results(RESULT_SUM,1,score_index) end if TALLY diff --git a/src/global.F90 b/src/global.F90 index dd013b3a8..ee308bbef 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -22,7 +22,7 @@ module global use surface_header, only: SurfaceContainer use source_header, only: SourceDistribution use tally_header, only: TallyObject, TallyDerivative - use tally_filter_header, only: TallyFilterContainer + use tally_filter_header, only: TallyFilterContainer, TallyFilterMatch use trigger_header, only: KTrigger use timer_header, only: Timer use volume_header, only: VolumeCalculation @@ -143,8 +143,7 @@ module global type(RegularMesh), allocatable, target :: meshes(:) type(TallyObject), allocatable, target :: tallies(:) type(TallyFilterContainer), allocatable, target :: filters(:) - integer, allocatable :: matching_bins(:) - real(8), allocatable :: filter_weights(:) + type(TallyFilterMatch), allocatable :: filter_matches(:) ! Pointers for different tallies type(TallyObject), pointer :: user_tallies(:) => null() @@ -438,8 +437,7 @@ module global type(Nuclide0K), allocatable, target :: nuclides_0K(:) ! 0K nuclides info !$omp threadprivate(micro_xs, material_xs, fission_bank, n_bank, & -!$omp& trace, thread_id, current_work, matching_bins, & -!$omp& filter_weights) +!$omp& trace, thread_id, current_work, filter_matches) contains @@ -500,8 +498,7 @@ contains if (allocated(meshes)) deallocate(meshes) if (allocated(filters)) deallocate(filters) if (allocated(tallies)) deallocate(tallies) - if (allocated(matching_bins)) deallocate(matching_bins) - if (allocated(filter_weights)) deallocate(filter_weights) + if (allocated(filter_matches)) deallocate(filter_matches) ! Deallocate fission and source bank and entropy !$omp parallel diff --git a/src/initialize.F90 b/src/initialize.F90 index 566b5aad7..e9718fee1 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -107,7 +107,7 @@ contains call logarithmic_grid() end if - ! Allocate and setup tally stride, matching_bins, and tally maps + ! Allocate and setup tally stride, filter_matches, and tally maps call configure_tallies() ! Set up tally procedure pointers diff --git a/src/output.F90 b/src/output.F90 index 344b6c460..7dc4ef475 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -690,6 +690,7 @@ contains integer :: k ! loop index for scoring bins integer :: n ! loop index for nuclides integer :: l ! loop index for user scores + integer :: h ! loop index for tally filters integer :: indent ! number of spaces to preceed output integer :: filter_index ! index in results array for filters integer :: score_index ! scoring bin index @@ -802,7 +803,10 @@ contains ! to be used for a given tally. ! Initialize bins, filter level, and indentation - matching_bins(1:size(t % filter)) = 0 + do h = 1, size(t % filter) + call filter_matches(t % filter(h)) % bins % clear() + call filter_matches(t % filter(h)) % bins % push_back(0) + end do j = 1 indent = 0 @@ -812,16 +816,18 @@ contains if (size(t % filter) == 0) exit find_bin ! Increment bin combination - matching_bins(j) = matching_bins(j) + 1 + filter_matches(j) % bins % data(1) = & + filter_matches(j) % bins % data(1) + 1 ! ================================================================= ! REACHED END OF BINS FOR THIS FILTER, MOVE TO NEXT FILTER - if (matching_bins(j) > filters(t % filter(j)) % obj % n_bins) then + if (filter_matches(j) % bins % data(1) > & + filters(t % filter(j)) % obj % n_bins) then ! If this is the first filter, then exit if (j == 1) exit print_bin - matching_bins(j) = 0 + filter_matches(j) % bins % data(1) = 0 j = j - 1 indent = indent - 2 @@ -835,7 +841,7 @@ contains ! Print current filter information write(UNIT=unit_tally, FMT='(1X,2A)') repeat(" ", indent), & trim(filters(t % filter(j)) % obj % & - text_label(matching_bins(j))) + text_label(filter_matches(j) % bins % data(1))) indent = indent + 2 j = j + 1 end if @@ -846,19 +852,18 @@ contains if (size(t % filter) > 0) then write(UNIT=unit_tally, FMT='(1X,2A)') repeat(" ", indent), & trim(filters(t % filter(j)) % obj % & - text_label(matching_bins(j))) + text_label(filter_matches(j) % bins % data(1))) end if ! Determine scoring index for this bin combination -- note that unlike ! in the score_tally subroutine, we have to use max(bins,1) since all ! bins below the lowest filter level will be zeros - if (size(t % filter) > 0) then - filter_index = sum((max(matching_bins(1:size(t % filter)),1) - 1) & - * t % stride) + 1 - else - filter_index = 1 - end if + filter_index = 1 + do h = 1, size(t % filter) + filter_index = filter_index + (max(filter_matches(t % filter(h)) & + % bins % data(1),1) - 1) * t % stride(h) + end do ! Write results for this filter bin combination score_index = 0 @@ -958,6 +963,7 @@ contains integer, intent(in) :: unit_tally integer :: i ! mesh index + integer :: j ! loop index over tally filters integer :: ijk(3) ! indices of mesh cells integer :: n_dim ! number of mesh dimensions integer :: n_cells ! number of mesh cells @@ -968,25 +974,30 @@ contains integer :: n ! number of incoming energy bins integer :: filter_index ! index in results array for filters logical :: print_ebin ! should incoming energy bin be displayed? + logical :: energy_filters ! energy filters present character(MAX_LINE_LEN) :: string type(RegularMesh), pointer :: m ! Get pointer to mesh - i_filter_mesh = t % find_filter(FILTER_MESH) - i_filter_surf = t % find_filter(FILTER_SURFACE) - select type(filt => filters(t % filter(i_filter_mesh)) % obj) + i_filter_mesh = t % filter(t % find_filter(FILTER_MESH)) + i_filter_surf = t % filter(t % find_filter(FILTER_SURFACE)) + select type(filt => filters(i_filter_mesh) % obj) type is (MeshFilter) m => meshes(filt % mesh) end select ! initialize bins array - matching_bins(1:size(t % filter)) = 1 + do j = 1, size(t % filter) + call filter_matches(t % filter(j)) % bins % clear() + call filter_matches(t % filter(j)) % bins % push_back(1) + end do ! determine how many energy in bins there are - i_filter_ein = t % find_filter(FILTER_ENERGYIN) - if (i_filter_ein > 0) then + energy_filters = (t % find_filter(FILTER_ENERGYIN) > 0) + if (energy_filters) then print_ebin = .true. - n = filters(t % filter(i_filter_ein)) % obj % n_bins + i_filter_ein = t % filter(t % find_filter(FILTER_ENERGYIN)) + n = filters(i_filter_ein) % obj % n_bins else print_ebin = .false. n = 1 @@ -1001,7 +1012,7 @@ contains ! Get the indices for this cell call bin_to_mesh_indices(m, i, ijk) - matching_bins(i_filter_mesh) = i + filter_matches(i_filter_mesh) % bins % data(1) = i ! Write the header for this cell if (n_dim == 1) then @@ -1019,43 +1030,55 @@ contains do l = 1, n if (print_ebin) then ! Set incoming energy bin - matching_bins(i_filter_ein) = l + filter_matches(i_filter_ein) % bins % data(1) = l ! Write incoming energy bin write(UNIT=unit_tally, FMT='(3X,A)') & - trim(filters(t % filter(i_filter_ein)) % obj % text_label( & - matching_bins(i_filter_ein))) + trim(filters(i_filter_ein) % obj % text_label( & + filter_matches(i_filter_ein) % bins % data(1))) end if ! Left Surface - matching_bins(i_filter_surf) = OUT_LEFT - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_LEFT + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Left", & to_str(t % results(RESULT_SUM,1,filter_index)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) - matching_bins(i_filter_surf) = IN_LEFT - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_LEFT + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Left", & to_str(t % results(RESULT_SUM,1,filter_index)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) ! Right Surface - matching_bins(i_filter_surf) = OUT_RIGHT - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_RIGHT + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Right", & to_str(t % results(RESULT_SUM,1,filter_index)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) - matching_bins(i_filter_surf) = IN_RIGHT - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_RIGHT + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Right", & to_str(t % results(RESULT_SUM,1,filter_index)), & @@ -1064,34 +1087,46 @@ contains if (n_dim >= 2) then ! Back Surface - matching_bins(i_filter_surf) = OUT_BACK - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_BACK + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Back", & to_str(t % results(RESULT_SUM,1,filter_index)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) - matching_bins(i_filter_surf) = IN_BACK - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_BACK + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Back", & to_str(t % results(RESULT_SUM,1,filter_index)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) ! Front Surface - matching_bins(i_filter_surf) = OUT_FRONT - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_FRONT + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Net Current on Front", & to_str(t % results(RESULT_SUM,1,filter_index)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) - matching_bins(i_filter_surf) = IN_FRONT - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_FRONT + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Net Current on Front", & to_str(t % results(RESULT_SUM,1,filter_index)), & @@ -1100,34 +1135,46 @@ contains if (n_dim == 3) then ! Bottom Surface - matching_bins(i_filter_surf) = OUT_BOTTOM - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_BOTTOM + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Bottom", & to_str(t % results(RESULT_SUM,1,filter_index)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) - matching_bins(i_filter_surf) = IN_BOTTOM - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_BOTTOM + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Bottom", & to_str(t % results(RESULT_SUM,1,filter_index)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) ! Top Surface - matching_bins(i_filter_surf) = OUT_TOP - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_TOP + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Top", & to_str(t % results(RESULT_SUM,1,filter_index)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) - matching_bins(i_filter_surf) = IN_TOP - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = IN_TOP + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) & + % bins % data(1) - 1) * t % stride(j) + end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Top", & to_str(t % results(RESULT_SUM,1,filter_index)), & diff --git a/src/tally.F90 b/src/tally.F90 index 02ab07339..fab30485d 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2204,14 +2204,16 @@ contains type(Particle), intent(in) :: p - integer :: i + integer :: i, j integer :: i_tally integer :: i_filt + integer :: i_bin integer :: k ! loop index for nuclide bins - ! position during the loop integer :: filter_index ! single index for single bin integer :: i_nuclide ! index in nuclides array + integer :: matching_bin ! next valid filter bin real(8) :: filter_weight ! combined weight of all filters + logical :: finished ! found all valid bin combinations type(TallyObject), pointer :: t ! A loop over all tallies is necessary because we need to simultaneously @@ -2222,15 +2224,29 @@ contains i_tally = active_analog_tallies % data(i) t => tallies(i_tally) - ! Find the first bin in each filter. There may be more than one matching - ! bin per filter, but we'll deal with those later. - do i_filt = 1, size(t % filter) - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, NO_BIN_FOUND, matching_bins(i_filt), & - filter_weights(i_filt)) + ! Find all valid bins in each filter if they have not already been found + ! for a previous tally. + do j = 1, size(t % filter) + i_filt = t % filter(j) + if (.not. filter_matches(i_filt) % bins_present) then + call filter_matches(i_filt) % bins % clear() + call filter_matches(i_filt) % weights % clear() + matching_bin = NO_BIN_FOUND + do + call filters(i_filt) % obj % get_next_bin(p, t % estimator, & + matching_bin, matching_bin, filter_weight) + if (matching_bin == NO_BIN_FOUND) exit + call filter_matches(i_filt) % bins % push_back(matching_bin) + call filter_matches(i_filt) % weights % push_back(filter_weight) + end do + filter_matches(i_filt) % bins_present = .true. + end if ! If there are no valid bins for this filter, then there is nothing to ! score and we can move on to the next tally. - if (matching_bins(i_filt) == NO_BIN_FOUND) cycle TALLY_LOOP + if (filter_matches(i_filt) % bins % size() == 0) cycle TALLY_LOOP + + ! Set the index of the bin used in the first filter combination + filter_matches(i_filt) % i_bin = 1 end do ! ======================================================================== @@ -2238,10 +2254,19 @@ contains FILTER_LOOP: do + ! Reset scoring index and weight + filter_index = 1 + filter_weight = 1 + ! Determine scoring index and weight for this filter combination - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filter))) + do j = 1, size(t % filter) + i_filt = t % filter(j) + i_bin = filter_matches(i_filt) % i_bin + filter_index = filter_index + (filter_matches(i_filt) % bins % & + data(i_bin) - 1) * t % stride(j) + filter_weight = filter_weight * filter_matches(i_filt) % weights % & + data(i_bin) + end do ! ====================================================================== ! Nuclide logic @@ -2294,31 +2319,25 @@ contains ! If there are no filters, then we are done. if (size(t % filter) == 0) exit FILTER_LOOP - ! Increment the filter bins, starting with the last filter. If we get a - ! NO_BIN_FOUND for the last filter, it means we finished all valid bins - ! for that filter, but next-to-last filter might have more than one - ! valid bin so we need to increment that one as well, and so on. - do i_filt = size(t % filter), 1, -1 - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, matching_bins(i_filt), matching_bins(i_filt), & - filter_weights(i_filt)) - if (matching_bins(i_filt) /= NO_BIN_FOUND) exit - end do - - ! If we got all NO_BIN_FOUNDs, then we have finished all valid bins for - ! each of the filters. Exit the loop. - if (all(matching_bins(:size(t % filter)) == NO_BIN_FOUND)) & - exit FILTER_LOOP - - ! Reset all the filters with NO_BIN_FOUND. This will set them back to - ! their first valid bin. - do i_filt = 1, size(t % filter) - if (matching_bins(i_filt) == NO_BIN_FOUND) then - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, matching_bins(i_filt), matching_bins(i_filt), & - filter_weights(i_filt)) + ! Increment the filter bins, starting with the last filter to find the + ! next valid bin combination + finished = .true. + do j = size(t % filter), 1, -1 + i_filt = t % filter(j) + if (filter_matches(i_filt) % i_bin < filter_matches(i_filt) % & + bins % size()) then + filter_matches(i_filt) % i_bin = filter_matches(i_filt) % i_bin + 1 + finished = .false. + exit + else + filter_matches(i_filt) % i_bin = 1 end if end do + + ! Once we have finished all valid bins for each of the filters, exit + ! the loop. + if (finished) exit FILTER_LOOP + end do FILTER_LOOP ! If the user has specified that we can assume all tallies are spatially @@ -2330,6 +2349,11 @@ contains end do TALLY_LOOP + ! Reset filter matches flag + do i = 1, n_filters + filter_matches(i) % bins_present = .false. + end do + ! Reset tally map positioning position = 0 @@ -2339,15 +2363,17 @@ contains type(Particle), intent(in) :: p - integer :: i, m + integer :: i, j, m integer :: i_tally integer :: i_filt + integer :: i_bin integer :: k ! loop index for nuclide bins - ! position during the loop integer :: filter_index ! single index for single bin integer :: i_nuclide ! index in nuclides array + integer :: matching_bin ! next valid filter bin real(8) :: filter_weight ! combined weight of all filters real(8) :: atom_density + logical :: finished ! found all valid bin combinations type(TallyObject), pointer :: t type(Material), pointer :: mat @@ -2363,15 +2389,29 @@ contains ! nuclides are in the material mat => materials(p % material) - ! Find the first bin in each filter. There may be more than one matching - ! bin per filter, but we'll deal with those later. - do i_filt = 1, size(t % filter) - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, NO_BIN_FOUND, matching_bins(i_filt), & - filter_weights(i_filt)) + ! Find all valid bins in each filter if they have not already been found + ! for a previous tally. + do j = 1, size(t % filter) + i_filt = t % filter(j) + if (.not. filter_matches(i_filt) % bins_present) then + call filter_matches(i_filt) % bins % clear() + call filter_matches(i_filt) % weights % clear() + matching_bin = NO_BIN_FOUND + do + call filters(i_filt) % obj % get_next_bin(p, t % estimator, & + matching_bin, matching_bin, filter_weight) + if (matching_bin == NO_BIN_FOUND) exit + call filter_matches(i_filt) % bins % push_back(matching_bin) + call filter_matches(i_filt) % weights % push_back(filter_weight) + end do + filter_matches(i_filt) % bins_present = .true. + end if ! If there are no valid bins for this filter, then there is nothing to ! score and we can move on to the next tally. - if (matching_bins(i_filt) == NO_BIN_FOUND) cycle TALLY_LOOP + if (filter_matches(i_filt) % bins % size() == 0) cycle TALLY_LOOP + + ! Set the index of the bin used in the first filter combination + filter_matches(i_filt) % i_bin = 1 end do ! ======================================================================== @@ -2379,10 +2419,19 @@ contains FILTER_LOOP: do + ! Reset scoring index and weight + filter_index = 1 + filter_weight = 1 + ! Determine scoring index and weight for this filter combination - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filter))) + do j = 1, size(t % filter) + i_filt = t % filter(j) + i_bin = filter_matches(i_filt) % i_bin + filter_index = filter_index + (filter_matches(i_filt) % bins % & + data(i_bin) - 1) * t % stride(j) + filter_weight = filter_weight * filter_matches(i_filt) % weights % & + data(i_bin) + end do ! ====================================================================== ! Nuclide logic @@ -2423,31 +2472,25 @@ contains ! If there are no filters, then we are done. if (size(t % filter) == 0) exit FILTER_LOOP - ! Increment the filter bins, starting with the last filter. If we get a - ! NO_BIN_FOUND for the last filter, it means we finished all valid bins - ! for that filter, but next-to-last filter might have more than one - ! valid bin so we need to increment that one as well, and so on. - do i_filt = size(t % filter), 1, -1 - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, matching_bins(i_filt), matching_bins(i_filt), & - filter_weights(i_filt)) - if (matching_bins(i_filt) /= NO_BIN_FOUND) exit - end do - - ! If we got all NO_BIN_FOUNDs, then we have finished all valid bins for - ! each of the filters. Exit the loop. - if (all(matching_bins(:size(t % filter)) == NO_BIN_FOUND)) & - exit FILTER_LOOP - - ! Reset all the filters with NO_BIN_FOUND. This will set them back to - ! their first valid bin. - do i_filt = 1, size(t % filter) - if (matching_bins(i_filt) == NO_BIN_FOUND) then - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, matching_bins(i_filt), matching_bins(i_filt), & - filter_weights(i_filt)) + ! Increment the filter bins, starting with the last filter to find the + ! next valid bin combination + finished = .true. + do j = size(t % filter), 1, -1 + i_filt = t % filter(j) + if (filter_matches(i_filt) % i_bin < filter_matches(i_filt) % & + bins % size()) then + filter_matches(i_filt) % i_bin = filter_matches(i_filt) % i_bin + 1 + finished = .false. + exit + else + filter_matches(i_filt) % i_bin = 1 end if end do + + ! Once we have finished all valid bins for each of the filters, exit + ! the loop. + if (finished) exit FILTER_LOOP + end do FILTER_LOOP ! If the user has specified that we can assume all tallies are spatially @@ -2459,6 +2502,11 @@ contains end do TALLY_LOOP + ! Reset filter matches flag + do i = 1, n_filters + filter_matches(i) % bins_present = .false. + end do + ! Reset tally map positioning position = 0 @@ -2485,6 +2533,10 @@ contains integer :: d_bin ! delayed group bin index integer :: n ! number of energies on filter integer :: k ! loop index for bank sites + integer :: l ! loop index for tally filters + integer :: f ! index in filters array + integer :: b ! index of filter bin + integer :: i_bin ! index of matching filter bin integer :: bin_energyout ! original outgoing energy bin integer :: i_filter ! index for matching filter bin combination real(8) :: filter_weight ! combined weight of all filters @@ -2493,11 +2545,12 @@ contains integer :: g_out ! energy group of fission bank site ! save original outgoing energy bin and score index - i = t % find_filter(FILTER_ENERGYOUT) - bin_energyout = matching_bins(i) + i = t % filter(t % find_filter(FILTER_ENERGYOUT)) + i_bin = filter_matches(i) % i_bin + bin_energyout = filter_matches(i) % bins % data(i_bin) ! declare the energyout filter type - select type(eo_filt => filters(t % filter(i)) % obj) + select type(eo_filt => filters(i) % obj) type is (EnergyoutFilter) ! Get number of energies on filter @@ -2534,7 +2587,7 @@ contains g_out = size(eo_filt % bins) - g_out ! change outgoing energy bin - matching_bins(i) = g_out + filter_matches(i) % bins % data(i_bin) = g_out else @@ -2550,7 +2603,8 @@ contains if (E_out < eo_filt % bins(1) .or. E_out > eo_filt % bins(n)) cycle ! change outgoing energy bin - matching_bins(i) = binary_search(eo_filt % bins, n, E_out) + filter_matches(i) % bins % data(i_bin) = & + binary_search(eo_filt % bins, n, E_out) end if @@ -2559,8 +2613,11 @@ contains (score_bin == SCORE_PROMPT_NU_FISSION .and. g == 0)) then ! determine scoring index and weight for this filter combination - i_filter = sum((matching_bins(1:size(t % filter)) - 1) * & - t % stride) + 1 + i_filter = 1 + do l = 1, size(t % filter) + i_filter = i_filter + (filter_matches(t % filter(l)) % bins % & + data(filter_matches(t % filter(l)) % i_bin) - 1) * t % stride(l) + end do ! Add score to tally !$omp atomic @@ -2590,11 +2647,20 @@ contains ! the delayed group of this bin if (d == g) then + ! Reset scoring index and filter weight + i_filter = 1 + filter_weight = 1 + ! determine scoring index and weight for this filter ! combination - i_filter = sum((matching_bins(1:size(t % filter)) - 1) * & - t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filter))) + do l = 1, size(t % filter) + f = t % filter(l) + b = filter_matches(f) % i_bin + i_filter = i_filter + (filter_matches(f) % bins % & + data(b) - 1) * t % stride(l) + filter_weight = filter_weight * filter_matches(f) % & + weights % data(b) + end do call score_fission_delayed_dg(t, d_bin, & score * filter_weight, i_score) @@ -2605,10 +2671,19 @@ contains ! if the delayed group filter is not present, add score to tally else + ! Reset scoring index and filter weight + i_filter = 1 + filter_weight = 1 + ! determine scoring index and weight for this filter combination - i_filter = sum((matching_bins(1:size(t % filter)) - 1) * & - t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filter))) + do l = 1, size(t % filter) + f = t % filter(l) + b = filter_matches(f) % i_bin + i_filter = i_filter + (filter_matches(f) % bins % data(b) - 1) & + * t % stride(l) + filter_weight = filter_weight * filter_matches(f) % weights % & + data(b) + end do ! Add score to tally !$omp atomic @@ -2620,7 +2695,7 @@ contains end select ! reset outgoing energy bin and score index - matching_bins(i) = bin_energyout + filter_matches(i) % bins % data(i_bin) = bin_energyout end subroutine score_fission_eout @@ -2636,23 +2711,31 @@ contains real(8), intent(in) :: score ! actual score integer, intent(in) :: score_index ! index for score + integer :: i ! loop over tally filters + integer :: i_filt ! index in filters array + integer :: i_bin ! index of matching filter bin integer :: bin_original ! original bin index integer :: filter_index ! index for matching filter bin combination ! save original delayed group bin - bin_original = matching_bins(t % find_filter(FILTER_DELAYEDGROUP)) - matching_bins(t % find_filter(FILTER_DELAYEDGROUP)) = d_bin + i_filt = t % filter(t % find_filter(FILTER_DELAYEDGROUP)) + i_bin = filter_matches(i_filt) % i_bin + bin_original = filter_matches(i_filt) % bins % data(i_bin) + filter_matches(i_filt) % bins % data(i_bin) = d_bin - ! determine scoring index and weight on the modified matching_bins - filter_index = sum((matching_bins(1:size(t % filter)) - 1) * & - t % stride) + 1 + ! determine scoring index and weight on the modified matching bins + filter_index = 1 + do i = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(i)) % bins % & + data(filter_matches(t % filter(i)) % i_bin) - 1) * t % stride(i) + end do !$omp atomic t % results(RESULT_VALUE, score_index, filter_index) = & t % results(RESULT_VALUE, score_index, filter_index) + score ! reset original delayed group bin - matching_bins(t % find_filter(FILTER_DELAYEDGROUP)) = bin_original + filter_matches(i_filt) % bins % data(i_bin) = bin_original end subroutine score_fission_delayed_dg @@ -2671,13 +2754,16 @@ contains integer :: i integer :: i_tally integer :: i_filt + integer :: i_bin integer :: j ! loop index for scoring bins integer :: k ! loop index for nuclide bins integer :: filter_index ! single index for single bin integer :: i_nuclide ! index in nuclides array (from bins) + integer :: matching_bin ! next valid filter bin real(8) :: flux ! tracklength estimate of flux real(8) :: atom_density ! atom density of single nuclide in atom/b-cm real(8) :: filter_weight ! combined weight of all filters + logical :: finished ! found all valid bin combinations type(TallyObject), pointer :: t type(Material), pointer :: mat @@ -2692,15 +2778,29 @@ contains i_tally = active_tracklength_tallies % data(i) t => tallies(i_tally) - ! Find the first bin in each filter. There may be more than one matching - ! bin per filter, but we'll deal with those later. - do i_filt = 1, size(t % filter) - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, NO_BIN_FOUND, matching_bins(i_filt), & - filter_weights(i_filt)) + ! Find all valid bins in each filter if they have not already been found + ! for a previous tally. + do j = 1, size(t % filter) + i_filt = t % filter(j) + if (.not. filter_matches(i_filt) % bins_present) then + call filter_matches(i_filt) % bins % clear() + call filter_matches(i_filt) % weights % clear() + matching_bin = NO_BIN_FOUND + do + call filters(i_filt) % obj % get_next_bin(p, t % estimator, & + matching_bin, matching_bin, filter_weight) + if (matching_bin == NO_BIN_FOUND) exit + call filter_matches(i_filt) % bins % push_back(matching_bin) + call filter_matches(i_filt) % weights % push_back(filter_weight) + end do + filter_matches(i_filt) % bins_present = .true. + end if ! If there are no valid bins for this filter, then there is nothing to ! score and we can move on to the next tally. - if (matching_bins(i_filt) == NO_BIN_FOUND) cycle TALLY_LOOP + if (filter_matches(i_filt) % bins % size() == 0) cycle TALLY_LOOP + + ! Set the index of the bin used in the first filter combination + filter_matches(i_filt) % i_bin = 1 end do ! ======================================================================== @@ -2708,10 +2808,19 @@ contains FILTER_LOOP: do + ! Reset scoring index and weight + filter_index = 1 + filter_weight = 1 + ! Determine scoring index and weight for this filter combination - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filter))) + do j = 1, size(t % filter) + i_filt = t % filter(j) + i_bin = filter_matches(i_filt) % i_bin + filter_index = filter_index + (filter_matches(i_filt) % bins % & + data(i_bin) - 1) * t % stride(j) + filter_weight = filter_weight * filter_matches(i_filt) % weights % & + data(i_bin) + end do ! ====================================================================== ! Nuclide logic @@ -2765,31 +2874,25 @@ contains ! If there are no filters, then we are done. if (size(t % filter) == 0) exit FILTER_LOOP - ! Increment the filter bins, starting with the last filter. If we get a - ! NO_BIN_FOUND for the last filter, it means we finished all valid bins - ! for that filter, but next-to-last filter might have more than one - ! valid bin so we need to increment that one as well, and so on. - do i_filt = size(t % filter), 1, -1 - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, matching_bins(i_filt), matching_bins(i_filt), & - filter_weights(i_filt)) - if (matching_bins(i_filt) /= NO_BIN_FOUND) exit - end do - - ! If we got all NO_BIN_FOUNDs, then we have finished all valid bins for - ! each of the filters. Exit the loop. - if (all(matching_bins(:size(t % filter)) == NO_BIN_FOUND)) & - exit FILTER_LOOP - - ! Reset all the filters with NO_BIN_FOUND. This will set them back to - ! their first valid bin. - do i_filt = 1, size(t % filter) - if (matching_bins(i_filt) == NO_BIN_FOUND) then - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, matching_bins(i_filt), matching_bins(i_filt), & - filter_weights(i_filt)) + ! Increment the filter bins, starting with the last filter to find the + ! next valid bin combination + finished = .true. + do j = size(t % filter), 1, -1 + i_filt = t % filter(j) + if (filter_matches(i_filt) % i_bin < filter_matches(i_filt) % & + bins % size()) then + filter_matches(i_filt) % i_bin = filter_matches(i_filt) % i_bin + 1 + finished = .false. + exit + else + filter_matches(i_filt) % i_bin = 1 end if end do + + ! Once we have finished all valid bins for each of the filters, exit + ! the loop. + if (finished) exit FILTER_LOOP + end do FILTER_LOOP ! If the user has specified that we can assume all tallies are spatially @@ -2801,6 +2904,11 @@ contains end do TALLY_LOOP + ! Reset filter matches flag + do i = 1, n_filters + filter_matches(i) % bins_present = .false. + end do + ! Reset tally map positioning position = 0 @@ -2821,14 +2929,17 @@ contains integer :: i integer :: i_tally integer :: i_filt + integer :: i_bin integer :: j ! loop index for scoring bins integer :: k ! loop index for nuclide bins integer :: filter_index ! single index for single bin integer :: i_nuclide ! index in nuclides array (from bins) + integer :: matching_bin ! next valid filter bin real(8) :: flux ! collision estimate of flux real(8) :: atom_density ! atom density of single nuclide ! in atom/b-cm real(8) :: filter_weight ! combined weight of all filters + logical :: finished ! found all valid bin combinations type(TallyObject), pointer :: t type(Material), pointer :: mat @@ -2848,15 +2959,29 @@ contains i_tally = active_collision_tallies % data(i) t => tallies(i_tally) - ! Find the first bin in each filter. There may be more than one matching - ! bin per filter, but we'll deal with those later. - do i_filt = 1, size(t % filter) - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, NO_BIN_FOUND, matching_bins(i_filt), & - filter_weights(i_filt)) + ! Find all valid bins in each filter if they have not already been found + ! for a previous tally. + do j = 1, size(t % filter) + i_filt = t % filter(j) + if (.not. filter_matches(i_filt) % bins_present) then + call filter_matches(i_filt) % bins % clear() + call filter_matches(i_filt) % weights % clear() + matching_bin = NO_BIN_FOUND + do + call filters(i_filt) % obj % get_next_bin(p, t % estimator, & + matching_bin, matching_bin, filter_weight) + if (matching_bin == NO_BIN_FOUND) exit + call filter_matches(i_filt) % bins % push_back(matching_bin) + call filter_matches(i_filt) % weights % push_back(filter_weight) + end do + filter_matches(i_filt) % bins_present = .true. + end if ! If there are no valid bins for this filter, then there is nothing to ! score and we can move on to the next tally. - if (matching_bins(i_filt) == NO_BIN_FOUND) cycle TALLY_LOOP + if (filter_matches(i_filt) % bins % size() == 0) cycle TALLY_LOOP + + ! Set the index of the bin used in the first filter combination + filter_matches(i_filt) % i_bin = 1 end do ! ======================================================================== @@ -2864,10 +2989,19 @@ contains FILTER_LOOP: do + ! Reset scoring index and weight + filter_index = 1 + filter_weight = 1 + ! Determine scoring index and weight for this filter combination - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 - filter_weight = product(filter_weights(:size(t % filter))) + do j = 1, size(t % filter) + i_filt = t % filter(j) + i_bin = filter_matches(i_filt) % i_bin + filter_index = filter_index + (filter_matches(i_filt) % bins % & + data(i_bin) - 1) * t % stride(j) + filter_weight = filter_weight * filter_matches(i_filt) % weights % & + data(i_bin) + end do ! ====================================================================== ! Nuclide logic @@ -2921,31 +3055,25 @@ contains ! If there are no filters, then we are done. if (size(t % filter) == 0) exit FILTER_LOOP - ! Increment the filter bins, starting with the last filter. If we get a - ! NO_BIN_FOUND for the last filter, it means we finished all valid bins - ! for that filter, but next-to-last filter might have more than one - ! valid bin so we need to increment that one as well, and so on. - do i_filt = size(t % filter), 1, -1 - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, matching_bins(i_filt), matching_bins(i_filt), & - filter_weights(i_filt)) - if (matching_bins(i_filt) /= NO_BIN_FOUND) exit - end do - - ! If we got all NO_BIN_FOUNDs, then we have finished all valid bins for - ! each of the filters. Exit the loop. - if (all(matching_bins(:size(t % filter)) == NO_BIN_FOUND)) & - exit FILTER_LOOP - - ! Reset all the filters with NO_BIN_FOUND. This will set them back to - ! their first valid bin. - do i_filt = 1, size(t % filter) - if (matching_bins(i_filt) == NO_BIN_FOUND) then - call filters(t % filter(i_filt)) % obj % get_next_bin(p, & - t % estimator, matching_bins(i_filt), matching_bins(i_filt), & - filter_weights(i_filt)) + ! Increment the filter bins, starting with the last filter to find the + ! next valid bin combination + finished = .true. + do j = size(t % filter), 1, -1 + i_filt = t % filter(j) + if (filter_matches(i_filt) % i_bin < filter_matches(i_filt) % & + bins % size()) then + filter_matches(i_filt) % i_bin = filter_matches(i_filt) % i_bin + 1 + finished = .false. + exit + else + filter_matches(i_filt) % i_bin = 1 end if end do + + ! Once we have finished all valid bins for each of the filters, exit + ! the loop. + if (finished) exit FILTER_LOOP + end do FILTER_LOOP ! If the user has specified that we can assume all tallies are spatially @@ -2957,6 +3085,11 @@ contains end do TALLY_LOOP + ! Reset filter matches flag + do i = 1, n_filters + filter_matches(i) % bins_present = .false. + end do + ! Reset tally map positioning position = 0 @@ -2973,7 +3106,7 @@ contains integer :: i integer :: i_tally - integer :: j ! loop indices + integer :: j, k ! loop indices integer :: n_dim ! num dimensions of the mesh integer :: d1 ! dimension index integer :: d2 ! dimension index @@ -2992,9 +3125,11 @@ contains real(8) :: d(3) ! distance to each bounding surface real(8) :: distance ! actual distance traveled real(8) :: filt_score ! score applied by filters + integer :: matching_bin ! next valid filter bin logical :: start_in_mesh ! particle's starting xyz in mesh? logical :: end_in_mesh ! particle's ending xyz in mesh? logical :: cross_surface ! whether the particle crosses a surface + logical :: energy_filter ! energy filter present type(TallyObject), pointer :: t type(RegularMesh), pointer :: m @@ -3007,13 +3142,25 @@ contains i_tally = active_current_tallies % data(i) t => tallies(i_tally) + ! Check for energy filter + energy_filter = (t % find_filter(FILTER_ENERGYIN) > 0) + ! Get index for mesh, surface, and energy filters - i_filter_mesh = t % find_filter(FILTER_MESH) - i_filter_surf = t % find_filter(FILTER_SURFACE) - i_filter_energy = t % find_filter(FILTER_ENERGYIN) + i_filter_mesh = t % filter(t % find_filter(FILTER_MESH)) + i_filter_surf = t % filter(t % find_filter(FILTER_SURFACE)) + if (energy_filter) then + i_filter_energy = t % filter(t % find_filter(FILTER_ENERGYIN)) + end if + + ! Reset the matching bins arrays + call filter_matches(i_filter_mesh) % bins % resize(1) + call filter_matches(i_filter_surf) % bins % resize(1) + if (energy_filter) then + call filter_matches(i_filter_energy) % bins % resize(1) + end if ! Get pointer to mesh - select type(filt => filters(t % filter(i_filter_mesh)) % obj) + select type(filt => filters(i_filter_mesh) % obj) type is (MeshFilter) m => meshes(filt % mesh) end select @@ -3047,11 +3194,11 @@ contains ! Determine incoming energy bin. We need to tell the energy filter this ! is a tracklength tally so it uses the pre-collision energy. - if (i_filter_energy > 0) then - call filters(t % filter(i_filter_energy)) % obj % get_next_bin(p, & - ESTIMATOR_TRACKLENGTH, NO_BIN_FOUND, & - matching_bins(i_filter_energy), filt_score) - if (matching_bins(i_filter_energy) == NO_BIN_FOUND) cycle + if (energy_filter) then + call filters(i_filter_energy) % obj % get_next_bin(p, & + ESTIMATOR_TRACKLENGTH, NO_BIN_FOUND, matching_bin, filt_score) + if (matching_bin == NO_BIN_FOUND) cycle + filter_matches(i_filter_energy) % bins % data(1) = matching_bin end if ! Bounding coordinates @@ -3065,7 +3212,7 @@ contains do j = 1, n_cross ! Reset scoring bin index - matching_bins(i_filter_surf) = 0 + filter_matches(i_filter_surf) % bins % data(1) = 0 ! Set the distances to infinity d = INFINITY @@ -3107,11 +3254,14 @@ contains ! Outward current on d1 max surface if (all(ijk0(:n_dim) >= 1) .and. & all(ijk0(:n_dim) <= m % dimension)) then - matching_bins(i_filter_surf) = d1 * 4 - 1 - matching_bins(i_filter_mesh) = & + filter_matches(i_filter_surf) % bins % data(1) = d1 * 4 - 1 + filter_matches(i_filter_mesh) % bins % data(1) = & mesh_indices_to_bin(m, ijk0) - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_index = 1 + do k = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % & + filter(k)) % bins % data(1) - 1) * t % stride(k) + end do !$omp atomic t % results(RESULT_VALUE, 1, filter_index) = & t % results(RESULT_VALUE, 1, filter_index) + p % wgt @@ -3143,11 +3293,14 @@ contains ! If the particle crossed the surface, tally the current if (cross_surface) then ijk0(d1) = ijk0(d1) + 1 - matching_bins(i_filter_surf) = d1 * 4 - 2 - matching_bins(i_filter_mesh) = & + filter_matches(i_filter_surf) % bins % data(1) = d1 * 4 - 2 + filter_matches(i_filter_mesh) % bins % data(1) = & mesh_indices_to_bin(m, ijk0) - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_index = 1 + do k = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % & + filter(k)) % bins % data(1) - 1) * t % stride(k) + end do !$omp atomic t % results(RESULT_VALUE, 1, filter_index) = & t % results(RESULT_VALUE, 1, filter_index) + p % wgt @@ -3163,11 +3316,14 @@ contains ! Outward current on d1 min surface if (all(ijk0(:n_dim) >= 1) .and. & all(ijk0(:n_dim) <= m % dimension)) then - matching_bins(i_filter_surf) = d1 * 4 - 3 - matching_bins(i_filter_mesh) = & + filter_matches(i_filter_surf) % bins % data(1) = d1 * 4 - 3 + filter_matches(i_filter_mesh) % bins % data(1) = & mesh_indices_to_bin(m, ijk0) - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_index = 1 + do k = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % & + filter(k)) % bins % data(1) - 1) * t % stride(k) + end do !$omp atomic t % results(RESULT_VALUE, 1, filter_index) = & t % results(RESULT_VALUE, 1, filter_index) + p % wgt @@ -3199,11 +3355,14 @@ contains ! If the particle crossed the surface, tally the current if (cross_surface) then ijk0(d1) = ijk0(d1) - 1 - matching_bins(i_filter_surf) = d1 * 4 - matching_bins(i_filter_mesh) = & + filter_matches(i_filter_surf) % bins % data(1) = d1 * 4 + filter_matches(i_filter_mesh) % bins % data(1) = & mesh_indices_to_bin(m, ijk0) - filter_index = sum((matching_bins(1:size(t % filter)) - 1) & - * t % stride) + 1 + filter_index = 1 + do k = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % & + filter(k)) % bins % data(1) - 1) * t % stride(k) + end do !$omp atomic t % results(RESULT_VALUE, 1, filter_index) = & t % results(RESULT_VALUE, 1, filter_index) + p % wgt diff --git a/src/tally_filter_header.F90 b/src/tally_filter_header.F90 index d934f63ff..350070e57 100644 --- a/src/tally_filter_header.F90 +++ b/src/tally_filter_header.F90 @@ -2,11 +2,25 @@ module tally_filter_header use constants, only: MAX_LINE_LEN use particle_header, only: Particle + use stl_vector, only: VectorInt, VectorReal use hdf5 implicit none +!=============================================================================== +! TALLYFILTERMATCH stores every valid bin and weight for a filter +!=============================================================================== + + type TallyFilterMatch + integer :: i_bin + type(VectorInt) :: bins + type(VectorReal) :: weights + + ! Indicates whether all valid bins for this filter have been found + logical :: bins_present = .false. + end type TallyFilterMatch + !=============================================================================== ! TALLYFILTER describes a filter that limits what events score to a tally. For ! example, a cell filter indicates that only particles in a specified cell diff --git a/src/tally_initialize.F90 b/src/tally_initialize.F90 index 8baabcd82..46c028364 100644 --- a/src/tally_initialize.F90 +++ b/src/tally_initialize.F90 @@ -29,7 +29,7 @@ contains !=============================================================================== ! SETUP_TALLY_ARRAYS allocates and populates several member arrays of the -! TallyObject derived type, including stride, matching_bins, and results. +! TallyObject derived type, including stride, filter_matches, and results. !=============================================================================== subroutine setup_tally_arrays() @@ -38,21 +38,18 @@ contains integer :: j ! loop index for filters integer :: n ! temporary stride integer :: i_filt ! filter index - integer :: max_n_filters = 0 ! maximum number of filters type(TallyObject), pointer :: t TALLY_LOOP: do i = 1, n_tallies ! Get pointer to tally t => tallies(i) - ! Allocate stride and matching_bins arrays + ! Allocate stride allocate(t % stride(size(t % filter))) - max_n_filters = max(max_n_filters, size(t % filter)) ! The filters are traversed in opposite order so that the last filter has ! the shortest stride in memory and the first filter has the largest ! stride - n = 1 STRIDE: do j = size(t % filter), 1, -1 i_filt = t % filter(j) @@ -72,8 +69,7 @@ contains ! Allocate array for matching filter bins !$omp parallel - allocate(matching_bins(max_n_filters)) - allocate(filter_weights(max_n_filters)) + allocate(filter_matches(n_filters)) !$omp end parallel end subroutine setup_tally_arrays diff --git a/src/trigger.F90 b/src/trigger.F90 index 32f2549c8..9eb39e9cc 100644 --- a/src/trigger.F90 +++ b/src/trigger.F90 @@ -94,6 +94,7 @@ contains character(len=52), intent(inout) :: name ! "eigenvalue" or tally score integer :: i ! index in tallies array + integer :: j ! index in tally filters integer :: n ! loop index for nuclides integer :: s ! loop index for triggers integer :: filter_index ! index in results array for filters @@ -167,7 +168,10 @@ contains else ! Initialize bins, filter level - matching_bins(1:size(t % filter)) = 0 + do j = 1, size(t % filter) + call filter_matches(t % filter(j)) % bins % clear() + call filter_matches(t % filter(j)) % bins % push_back(0) + end do FILTER_LOOP: do filter_index = 1, t % total_filter_bins @@ -284,6 +288,7 @@ contains subroutine compute_tally_current(t, trigger) integer :: i ! mesh index + integer :: j ! loop index for tally filters integer :: ijk(3) ! indices of mesh cells integer :: n_dim ! number of mesh dimensions integer :: n_cells ! number of mesh cells @@ -301,21 +306,25 @@ contains type(RegularMesh), pointer :: m ! surface current mesh ! Get pointer to mesh - i_filter_mesh = t % find_filter(FILTER_MESH) - i_filter_surf = t % find_filter(FILTER_SURFACE) - select type(filt => filters(t % filter(i_filter_mesh)) % obj) + i_filter_mesh = t % filter(t % find_filter(FILTER_MESH)) + i_filter_surf = t % filter(t % find_filter(FILTER_SURFACE)) + select type(filt => filters(i_filter_mesh) % obj) type is (MeshFilter) m => meshes(filt % mesh) end select ! initialize bins array - matching_bins(1:size(t % filter)) = 1 + do j = 1, size(t % filter) + call filter_matches(t % filter(j)) % bins % clear() + call filter_matches(t % filter(j)) % bins % push_back(1) + end do ! determine how many energyin bins there are i_filter_ein = t % find_filter(FILTER_ENERGYIN) if (i_filter_ein > 0) then print_ebin = .true. n = filters(t % filter(i_filter_ein)) % obj % n_bins + i_filter_ein = t % filter(i_filter_ein) else print_ebin = .false. n = 1 @@ -330,18 +339,21 @@ contains ! Get the indices for this cell call bin_to_mesh_indices(m, i, ijk) - matching_bins(i_filter_mesh) = i + filter_matches(i_filter_mesh) % bins % data(1) = i do l = 1, n if (print_ebin) then - matching_bins(i_filter_ein) = l + filter_matches(i_filter_ein) % bins % data(1) = l end if ! Left Surface - matching_bins(i_filter_surf) = OUT_LEFT - filter_index = & - sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_LEFT + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) % & + bins % data(1) - 1) * t % stride(j) + end do call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -352,9 +364,12 @@ contains trigger % variance = std_dev**2 ! Right Surface - matching_bins(i_filter_surf) = OUT_RIGHT - filter_index = & - sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_RIGHT + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) % & + bins % data(1) - 1) * t % stride(j) + end do call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -365,9 +380,12 @@ contains trigger % variance = trigger % std_dev**2 ! Back Surface - matching_bins(i_filter_surf) = OUT_BACK - filter_index = & - sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_BACK + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) % & + bins % data(1) - 1) * t % stride(j) + end do call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -378,9 +396,12 @@ contains trigger % variance = trigger % std_dev**2 ! Front Surface - matching_bins(i_filter_surf) = OUT_FRONT - filter_index = & - sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_FRONT + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) % & + bins % data(1) - 1) * t % stride(j) + end do call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -391,9 +412,12 @@ contains trigger % variance = trigger % std_dev**2 ! Bottom Surface - matching_bins(i_filter_surf) = OUT_BOTTOM - filter_index = & - sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_BOTTOM + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) % & + bins % data(1) - 1) * t % stride(j) + end do call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev @@ -404,9 +428,12 @@ contains trigger % variance = trigger % std_dev**2 ! Top Surface - matching_bins(i_filter_surf) = OUT_TOP - filter_index = & - sum((matching_bins(1:size(t % filter)) - 1) * t % stride) + 1 + filter_matches(i_filter_surf) % bins % data(1) = OUT_TOP + filter_index = 1 + do j = 1, size(t % filter) + filter_index = filter_index + (filter_matches(t % filter(j)) % & + bins % data(1) - 1) * t % stride(j) + end do call get_trigger_uncertainty(std_dev, rel_err, 1, filter_index, t) if (trigger % std_dev < std_dev) then trigger % std_dev = std_dev diff --git a/tests/test_diff_tally/test_diff_tally.py b/tests/test_diff_tally/test_diff_tally.py index 51e4cd5eb..84aa18156 100644 --- a/tests/test_diff_tally/test_diff_tally.py +++ b/tests/test_diff_tally/test_diff_tally.py @@ -127,7 +127,6 @@ class DiffTallyTestHarness(PyAPITestHarness): # Extract the relevant data as a CSV string. cols = ('d_material', 'd_nuclide', 'd_variable', 'score', 'mean', 'std. dev.') - print(df.to_csv(None, columns=cols, index=False, float_format='%.7e')) return df.to_csv(None, columns=cols, index=False, float_format='%.7e') From 9028145a26a4bd22269fdd01338e62adcc7fb29d Mon Sep 17 00:00:00 2001 From: amandalund Date: Thu, 6 Apr 2017 14:29:34 -0500 Subject: [PATCH 15/18] Clean up --- src/cmfd_data.F90 | 113 +++++++++------------------------- src/output.F90 | 152 ++++++++++++++++++---------------------------- 2 files changed, 86 insertions(+), 179 deletions(-) diff --git a/src/cmfd_data.F90 b/src/cmfd_data.F90 index 2e304a909..7f327ca45 100644 --- a/src/cmfd_data.F90 +++ b/src/cmfd_data.F90 @@ -82,6 +82,7 @@ contains integer :: i_filter_ein ! index for incoming energy filter integer :: i_filter_eout ! index for outgoing energy filter integer :: i_filter_surf ! index for surface filter + integer :: stride_surf ! stride for surface filter logical :: energy_filters! energy filters present real(8) :: flux ! temp variable for flux type(TallyObject), pointer :: t ! pointer for tally object @@ -252,6 +253,7 @@ contains else if (ital == 3) then i_filter_surf = t % filter(t % find_filter(FILTER_SURFACE)) + stride_surf = t % stride(t % find_filter(FILTER_SURFACE)) ! Initialize and filter for energy do l = 1, size(t % filter) @@ -266,107 +268,48 @@ contains filter_matches(i_filter_mesh) % bins % data(1) = & mesh_indices_to_bin(m, (/ i, j, k /)) - ! Left surface - filter_matches(i_filter_surf) % bins % data(1) = OUT_LEFT score_index = 1 do l = 1, size(t % filter) + if (t % filter(l) == i_filter_surf) cycle score_index = score_index + (filter_matches(t % filter(l)) & % bins % data(1) - 1) * t % stride(l) end do - cmfd % current(1,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - filter_matches(i_filter_surf) % bins % data(1) = IN_LEFT - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(2,h,i,j,k) = t % results(RESULT_SUM,1,score_index) + ! Left surface + cmfd % current(1,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (OUT_LEFT - 1) * stride_surf) + cmfd % current(2,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (IN_LEFT - 1) * stride_surf) ! Right surface - filter_matches(i_filter_surf) % bins % data(1) = IN_RIGHT - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(3,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - - filter_matches(i_filter_surf) % bins % data(1) = OUT_RIGHT - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(4,h,i,j,k) = t % results(RESULT_SUM,1,score_index) + cmfd % current(3,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (IN_RIGHT - 1) * stride_surf) + cmfd % current(4,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (OUT_RIGHT - 1) * stride_surf) ! Back surface - filter_matches(i_filter_surf) % bins % data(1) = OUT_BACK - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(5,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - - filter_matches(i_filter_surf) % bins % data(1) = IN_BACK - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(6,h,i,j,k) = t % results(RESULT_SUM,1,score_index) + cmfd % current(5,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (OUT_BACK - 1) * stride_surf) + cmfd % current(6,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (IN_BACK - 1) * stride_surf) ! Front surface - filter_matches(i_filter_surf) % bins % data(1) = IN_FRONT - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(7,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - - filter_matches(i_filter_surf) % bins % data(1) = OUT_FRONT - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(8,h,i,j,k) = t % results(RESULT_SUM,1,score_index) + cmfd % current(7,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (IN_FRONT - 1) * stride_surf) + cmfd % current(8,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (OUT_FRONT - 1) * stride_surf) ! Bottom surface - filter_matches(i_filter_surf) % bins % data(1) = OUT_BOTTOM - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(9,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - - filter_matches(i_filter_surf) % bins % data(1) = IN_BOTTOM - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(10,h,i,j,k) = t % results(RESULT_SUM,1,score_index) + cmfd % current(9,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (OUT_BOTTOM - 1) * stride_surf) + cmfd % current(10,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (IN_BOTTOM - 1) * stride_surf) ! Top surface - filter_matches(i_filter_surf) % bins % data(1) = IN_TOP - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(11,h,i,j,k) = t % results(RESULT_SUM,1,score_index) - - filter_matches(i_filter_surf) % bins % data(1) = OUT_TOP - score_index = 1 - do l = 1, size(t % filter) - score_index = score_index + (filter_matches(t % filter(l)) & - % bins % data(1) - 1) * t % stride(l) - end do - cmfd % current(12,h,i,j,k) = t % results(RESULT_SUM,1,score_index) + cmfd % current(11,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (IN_TOP - 1) * stride_surf) + cmfd % current(12,h,i,j,k) = t % results(RESULT_SUM, 1, & + score_index + (OUT_TOP - 1) * stride_surf) end if TALLY diff --git a/src/output.F90 b/src/output.F90 index 7dc4ef475..2b00b0b07 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -971,6 +971,7 @@ contains integer :: i_filter_mesh ! index for mesh filter integer :: i_filter_ein ! index for incoming energy filter integer :: i_filter_surf ! index for surface filter + integer :: stride_surf ! stride for surface filter integer :: n ! number of incoming energy bins integer :: filter_index ! index in results array for filters logical :: print_ebin ! should incoming energy bin be displayed? @@ -980,12 +981,15 @@ contains ! Get pointer to mesh i_filter_mesh = t % filter(t % find_filter(FILTER_MESH)) - i_filter_surf = t % filter(t % find_filter(FILTER_SURFACE)) select type(filt => filters(i_filter_mesh) % obj) type is (MeshFilter) m => meshes(filt % mesh) end select + ! Get surface filter index and stride + i_filter_surf = t % filter(t % find_filter(FILTER_SURFACE)) + stride_surf = t % stride(t % find_filter(FILTER_SURFACE)) + ! initialize bins array do j = 1, size(t % filter) call filter_matches(t % filter(j)) % bins % clear() @@ -1038,147 +1042,107 @@ contains filter_matches(i_filter_ein) % bins % data(1))) end if - ! Left Surface - filter_matches(i_filter_surf) % bins % data(1) = OUT_LEFT filter_index = 1 do j = 1, size(t % filter) + if (t % filter(j) == i_filter_surf) cycle filter_index = filter_index + (filter_matches(t % filter(j)) & % bins % data(1) - 1) * t % stride(j) end do + + ! Left Surface write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Left", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) - - filter_matches(i_filter_surf) % bins % data(1) = IN_LEFT - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do + to_str(t % results(RESULT_SUM,1,filter_index + & + (OUT_LEFT - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (OUT_LEFT - 1) * stride_surf))) + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Left", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (IN_LEFT - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (IN_LEFT - 1) * stride_surf))) ! Right Surface - filter_matches(i_filter_surf) % bins % data(1) = OUT_RIGHT - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Right", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (OUT_RIGHT - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (OUT_RIGHT - 1) * stride_surf))) - filter_matches(i_filter_surf) % bins % data(1) = IN_RIGHT - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Right", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (IN_RIGHT - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (IN_RIGHT - 1) * stride_surf))) if (n_dim >= 2) then ! Back Surface - filter_matches(i_filter_surf) % bins % data(1) = OUT_BACK - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Back", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (OUT_BACK - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (OUT_BACK - 1) * stride_surf))) - filter_matches(i_filter_surf) % bins % data(1) = IN_BACK - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Back", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (IN_BACK - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (IN_BACK - 1) * stride_surf))) ! Front Surface - filter_matches(i_filter_surf) % bins % data(1) = OUT_FRONT - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Net Current on Front", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (OUT_FRONT - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (OUT_FRONT - 1) * stride_surf))) - filter_matches(i_filter_surf) % bins % data(1) = IN_FRONT - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Net Current on Front", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (IN_FRONT - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (IN_FRONT - 1) * stride_surf))) end if if (n_dim == 3) then + ! Bottom Surface - filter_matches(i_filter_surf) % bins % data(1) = OUT_BOTTOM - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Bottom", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (OUT_BOTTOM - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (OUT_BOTTOM - 1) * stride_surf))) - filter_matches(i_filter_surf) % bins % data(1) = IN_BOTTOM - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Bottom", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (IN_BOTTOM - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (IN_BOTTOM - 1) * stride_surf))) ! Top Surface - filter_matches(i_filter_surf) % bins % data(1) = OUT_TOP - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Outgoing Current on Top", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (OUT_TOP - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (OUT_TOP - 1) * stride_surf))) - filter_matches(i_filter_surf) % bins % data(1) = IN_TOP - filter_index = 1 - do j = 1, size(t % filter) - filter_index = filter_index + (filter_matches(t % filter(j)) & - % bins % data(1) - 1) * t % stride(j) - end do write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Top", & - to_str(t % results(RESULT_SUM,1,filter_index)), & - trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index))) + to_str(t % results(RESULT_SUM,1,filter_index + & + (IN_TOP - 1) * stride_surf)), & + trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & + (IN_TOP - 1) * stride_surf))) end if end do end do From cf6b71f7199b556810af558afb9c45b13833e888 Mon Sep 17 00:00:00 2001 From: amandalund Date: Fri, 5 May 2017 18:38:21 -0500 Subject: [PATCH 16/18] Address #871 comments --- openmc/tallies.py | 7 +--- src/cmfd_data.F90 | 2 +- src/output.F90 | 2 +- src/tally.F90 | 43 ++++++-------------- src/tally_filter.F90 | 11 +---- src/tally_filter_header.F90 | 1 + tests/test_filter_energyfun/results_true.dat | 2 +- 7 files changed, 19 insertions(+), 49 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 84fea7268..64bbe6f4a 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1077,12 +1077,9 @@ class Tally(object): # Optional Tally filters if len(self.filters) > 0: - filters = '' - for filt in self.filters: - filters += '{0} '.format(filt.id) - + filters = ' '.join(str(f.id) for f in self.filters) subelement = ET.SubElement(element, "filters") - subelement.text = filters.rstrip(' ') + subelement.text = filters # Optional Nuclides if len(self.nuclides) > 0: diff --git a/src/cmfd_data.F90 b/src/cmfd_data.F90 index 7f327ca45..177f140b6 100644 --- a/src/cmfd_data.F90 +++ b/src/cmfd_data.F90 @@ -254,7 +254,7 @@ contains i_filter_surf = t % filter(t % find_filter(FILTER_SURFACE)) stride_surf = t % stride(t % find_filter(FILTER_SURFACE)) - + ! Initialize and filter for energy do l = 1, size(t % filter) call filter_matches(t % filter(l)) % bins % clear() diff --git a/src/output.F90 b/src/output.F90 index 5f012ce48..a7d5e4cc6 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -1056,7 +1056,7 @@ contains (OUT_LEFT - 1) * stride_surf)), & trim(to_str(t % results(RESULT_SUM_SQ,1,filter_index + & (OUT_LEFT - 1) * stride_surf))) - + write(UNIT=unit_tally, FMT='(5X,A,T35,A,"+/- ",A)') & "Incoming Current on Left", & to_str(t % results(RESULT_SUM,1,filter_index + & diff --git a/src/tally.F90 b/src/tally.F90 index fda01c88b..0ee041cbe 100644 --- a/src/tally.F90 +++ b/src/tally.F90 @@ -2317,7 +2317,7 @@ contains ! Reset scoring index and weight filter_index = 1 - filter_weight = 1 + filter_weight = ONE ! Determine scoring index and weight for this filter combination do j = 1, size(t % filter) @@ -2377,9 +2377,6 @@ contains ! ====================================================================== ! Filter logic - ! If there are no filters, then we are done. - if (size(t % filter) == 0) exit FILTER_LOOP - ! Increment the filter bins, starting with the last filter to find the ! next valid bin combination finished = .true. @@ -2411,9 +2408,7 @@ contains end do TALLY_LOOP ! Reset filter matches flag - do i = 1, n_filters - filter_matches(i) % bins_present = .false. - end do + filter_matches(:) % bins_present = .false. ! Reset tally map positioning position = 0 @@ -2482,7 +2477,7 @@ contains ! Reset scoring index and weight filter_index = 1 - filter_weight = 1 + filter_weight = ONE ! Determine scoring index and weight for this filter combination do j = 1, size(t % filter) @@ -2530,9 +2525,6 @@ contains ! ====================================================================== ! Filter logic - ! If there are no filters, then we are done. - if (size(t % filter) == 0) exit FILTER_LOOP - ! Increment the filter bins, starting with the last filter to find the ! next valid bin combination finished = .true. @@ -2564,9 +2556,7 @@ contains end do TALLY_LOOP ! Reset filter matches flag - do i = 1, n_filters - filter_matches(i) % bins_present = .false. - end do + filter_matches(:) % bins_present = .false. ! Reset tally map positioning position = 0 @@ -2677,7 +2667,8 @@ contains i_filter = 1 do l = 1, size(t % filter) i_filter = i_filter + (filter_matches(t % filter(l)) % bins % & - data(filter_matches(t % filter(l)) % i_bin) - 1) * t % stride(l) + data(filter_matches(t % filter(l)) % i_bin) - 1) * & + t % stride(l) end do ! Add score to tally @@ -2710,7 +2701,7 @@ contains ! Reset scoring index and filter weight i_filter = 1 - filter_weight = 1 + filter_weight = ONE ! determine scoring index and weight for this filter ! combination @@ -2734,7 +2725,7 @@ contains ! Reset scoring index and filter weight i_filter = 1 - filter_weight = 1 + filter_weight = ONE ! determine scoring index and weight for this filter combination do l = 1, size(t % filter) @@ -2871,7 +2862,7 @@ contains ! Reset scoring index and weight filter_index = 1 - filter_weight = 1 + filter_weight = ONE ! Determine scoring index and weight for this filter combination do j = 1, size(t % filter) @@ -2932,9 +2923,6 @@ contains ! ====================================================================== ! Filter logic - ! If there are no filters, then we are done. - if (size(t % filter) == 0) exit FILTER_LOOP - ! Increment the filter bins, starting with the last filter to find the ! next valid bin combination finished = .true. @@ -2966,9 +2954,7 @@ contains end do TALLY_LOOP ! Reset filter matches flag - do i = 1, n_filters - filter_matches(i) % bins_present = .false. - end do + filter_matches(:) % bins_present = .false. ! Reset tally map positioning position = 0 @@ -3052,7 +3038,7 @@ contains ! Reset scoring index and weight filter_index = 1 - filter_weight = 1 + filter_weight = ONE ! Determine scoring index and weight for this filter combination do j = 1, size(t % filter) @@ -3113,9 +3099,6 @@ contains ! ====================================================================== ! Filter logic - ! If there are no filters, then we are done. - if (size(t % filter) == 0) exit FILTER_LOOP - ! Increment the filter bins, starting with the last filter to find the ! next valid bin combination finished = .true. @@ -3147,9 +3130,7 @@ contains end do TALLY_LOOP ! Reset filter matches flag - do i = 1, n_filters - filter_matches(i) % bins_present = .false. - end do + filter_matches(:) % bins_present = .false. ! Reset tally map positioning position = 0 diff --git a/src/tally_filter.F90 b/src/tally_filter.F90 index 0c316f73b..dfb89d433 100644 --- a/src/tally_filter.F90 +++ b/src/tally_filter.F90 @@ -1670,17 +1670,8 @@ contains call move_alloc(filters(i) % obj, temp(i) % obj) end do - ! Allocate filters array with increased size - deallocate(filters) - allocate(filters(size(temp))) - ! Move filters back from temporary array to filters array - do i = 1, n_filters - call move_alloc(temp(i) % obj, filters(i) % obj) - end do - - ! Deallocate temporary array - deallocate(temp) + call move_alloc(temp, filters) end if ! Set n_filters diff --git a/src/tally_filter_header.F90 b/src/tally_filter_header.F90 index 350070e57..061642545 100644 --- a/src/tally_filter_header.F90 +++ b/src/tally_filter_header.F90 @@ -13,6 +13,7 @@ module tally_filter_header !=============================================================================== type TallyFilterMatch + ! Index of the bin and weight being used in the current filter combination integer :: i_bin type(VectorInt) :: bins type(VectorReal) :: weights diff --git a/tests/test_filter_energyfun/results_true.dat b/tests/test_filter_energyfun/results_true.dat index d3dc3ad6a..8e48e5f3c 100644 --- a/tests/test_filter_energyfun/results_true.dat +++ b/tests/test_filter_energyfun/results_true.dat @@ -1,2 +1,2 @@ energyfunction nuclide score mean std. dev. -0 f4ae05cee02fae Am241 (n,gamma) 1.00e-01 6.22e-03 +0 ac03185c35fac8 Am241 (n,gamma) 1.00e-01 6.22e-03 From cd58aaefa7fa8274472ed74f9ddbb3aaf99477c3 Mon Sep 17 00:00:00 2001 From: amandalund Date: Tue, 9 May 2017 12:09:55 -0500 Subject: [PATCH 17/18] Fixed bug in write_tallies(): filter_matches index j --> t % filter(j) --- src/output.F90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/output.F90 b/src/output.F90 index a7d5e4cc6..10d4f0511 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -816,18 +816,18 @@ contains if (size(t % filter) == 0) exit find_bin ! Increment bin combination - filter_matches(j) % bins % data(1) = & - filter_matches(j) % bins % data(1) + 1 + filter_matches(t % filter(j)) % bins % data(1) = & + filter_matches(t % filter(j)) % bins % data(1) + 1 ! ================================================================= ! REACHED END OF BINS FOR THIS FILTER, MOVE TO NEXT FILTER - if (filter_matches(j) % bins % data(1) > & + if (filter_matches(t % filter(j)) % bins % data(1) > & filters(t % filter(j)) % obj % n_bins) then ! If this is the first filter, then exit if (j == 1) exit print_bin - filter_matches(j) % bins % data(1) = 0 + filter_matches(t % filter(j)) % bins % data(1) = 0 j = j - 1 indent = indent - 2 @@ -841,7 +841,7 @@ contains ! Print current filter information write(UNIT=unit_tally, FMT='(1X,2A)') repeat(" ", indent), & trim(filters(t % filter(j)) % obj % & - text_label(filter_matches(j) % bins % data(1))) + text_label(filter_matches(t % filter(j)) % bins % data(1))) indent = indent + 2 j = j + 1 end if @@ -852,7 +852,7 @@ contains if (size(t % filter) > 0) then write(UNIT=unit_tally, FMT='(1X,2A)') repeat(" ", indent), & trim(filters(t % filter(j)) % obj % & - text_label(filter_matches(j) % bins % data(1))) + text_label(filter_matches(t % filter(j)) % bins % data(1))) end if ! Determine scoring index for this bin combination -- note that unlike From 70cc2f63c3cc79b1b0d48eeee1b70217064310fb Mon Sep 17 00:00:00 2001 From: amandalund Date: Tue, 23 May 2017 13:07:40 -0500 Subject: [PATCH 18/18] Address #871 comments: incremented statepoint revision, updated documented tallies.xml format, updated tallies RELAX NG schema --- docs/source/io_formats/statepoint.rst | 2 +- docs/source/io_formats/tallies.rst | 77 ++++----- openmc/statepoint.py | 2 +- openmc/tallies.py | 3 +- src/cmfd_input.F90 | 6 +- src/constants.F90 | 2 +- src/relaxng/tallies.rnc | 23 ++- src/relaxng/tallies.rng | 236 ++++++++++++++------------ 8 files changed, 190 insertions(+), 161 deletions(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index b0321814f..f0f2af59b 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -4,7 +4,7 @@ State Point File Format ======================= -The current version of the statepoint file format is 16.0. +The current version of the statepoint file format is 17.0. **/** diff --git a/docs/source/io_formats/tallies.rst b/docs/source/io_formats/tallies.rst index 89468396e..9c0a2515e 100644 --- a/docs/source/io_formats/tallies.rst +++ b/docs/source/io_formats/tallies.rst @@ -18,8 +18,8 @@ filters can be used for a tally. The following types of filter are available: cell, universe, material, surface, birth region, pre-collision energy, post-collision energy, and an arbitrary structured mesh. -The three valid elements in the tallies.xml file are ````, ````, -and ````. +The five valid elements in the tallies.xml file are ````, ````, +````, ````, and ````. .. _tally: @@ -35,42 +35,8 @@ The ```` element accepts the following sub-elements: *Default*: "" - :filter: - Specify a filter that modifies tally behavior. Most tallies (e.g. ``cell``, - ``energy``, and ``material``) restrict the tally so that only particles - within certain regions of phase space contribute to the tally. Others - (e.g. ``delayedgroup`` and ``energyfunction``) can apply some other function - to the scored values. This element and its attributes/sub-elements are - described below. - - .. note:: - You may specify zero, one, or multiple filters to apply to the tally. To - specify multiple filters, you must use multiple ```` elements. - - The ``filter`` element has the following attributes/sub-elements: - - :type: - The type of the filter. Accepted options are "cell", "cellborn", - "material", "universe", "energy", "energyout", "mu", "polar", - "azimuthal", "mesh", "distribcell", "delayedgroup", and - "energyfunction". - - :bins: - A description of the bins for each type of filter can be found in - :ref:`filter_types`. - - :energy: - ``energyfunction`` filters multiply tally scores by an arbitrary - function. The function is described by a piecewise linear-linear set of - (energy, y) values. This entry specifies the energy values. The function - will be evaluated as zero outside of the bounds of this energy grid. - (Only used for ``energyfunction`` filters) - - :y: - ``energyfunction`` filters multiply tally scores by an arbitrary - function. The function is described by a piecewise linear-linear set of - (energy, y) values. This entry specifies the y values. (Only used - for ``energyfunction`` filters) + :filters: + A space-separated list of the IDs of ``filter`` elements. :nuclides: If specified, the scores listed will be for particular nuclides, not the @@ -144,6 +110,41 @@ The ```` element accepts the following sub-elements: *Default*: None + +-------------------- +```` Element +-------------------- + +Filters can be used to modify tally behavior. Most tallies (e.g. ``cell``, +``energy``, and ``material``) restrict the tally so that only particles +within certain regions of phase space contribute to the tally. Others +(e.g. ``delayedgroup`` and ``energyfunction``) can apply some other function +to the scored values. The ``filter`` element has the following +attributes/sub-elements: + + :type: + The type of the filter. Accepted options are "cell", "cellborn", + "material", "universe", "energy", "energyout", "mu", "polar", + "azimuthal", "mesh", "distribcell", "delayedgroup", and + "energyfunction". + + :bins: + A description of the bins for each type of filter can be found in + :ref:`filter_types`. + + :energy: + ``energyfunction`` filters multiply tally scores by an arbitrary + function. The function is described by a piecewise linear-linear set of + (energy, y) values. This entry specifies the energy values. The function + will be evaluated as zero outside of the bounds of this energy grid. + (Only used for ``energyfunction`` filters) + + :y: + ``energyfunction`` filters multiply tally scores by an arbitrary + function. The function is described by a piecewise linear-linear set of + (energy, y) values. This entry specifies the y values. (Only used + for ``energyfunction`` filters) + .. _filter_types: Filter Types diff --git a/openmc/statepoint.py b/openmc/statepoint.py index f42c772be..543e8a302 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -9,7 +9,7 @@ import h5py import openmc import openmc.checkvalue as cv -_VERSION_STATEPOINT = 16 +_VERSION_STATEPOINT = 17 class StatePoint(object): diff --git a/openmc/tallies.py b/openmc/tallies.py index 64bbe6f4a..1641d6164 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1077,9 +1077,8 @@ class Tally(object): # Optional Tally filters if len(self.filters) > 0: - filters = ' '.join(str(f.id) for f in self.filters) subelement = ET.SubElement(element, "filters") - subelement.text = filters + subelement.text = ' '.join(str(f.id) for f in self.filters) # Optional Nuclides if len(self.nuclides) > 0: diff --git a/src/cmfd_input.F90 b/src/cmfd_input.F90 index 91f2e03b6..d57c21beb 100644 --- a/src/cmfd_input.F90 +++ b/src/cmfd_input.F90 @@ -378,11 +378,7 @@ contains ! Determine number of filters energy_filters = check_for_node(node_mesh, "energy") - if (energy_filters) then - n_cmfd_filters = 5 - else - n_cmfd_filters = 3 - end if + n_cmfd_filters = merge(5, 3, energy_filters) ! Extend filters array so we can add CMFD filters call add_filters(n_cmfd_filters) diff --git a/src/constants.F90 b/src/constants.F90 index c44896b31..27adee989 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -16,7 +16,7 @@ module constants integer, parameter :: HDF5_VERSION(2) = [1, 0] ! Version numbers for binary files - integer, parameter :: VERSION_STATEPOINT(2) = [16, 0] + integer, parameter :: VERSION_STATEPOINT(2) = [17, 0] integer, parameter :: VERSION_PARTICLE_RESTART(2) = [2, 0] integer, parameter :: VERSION_TRACK(2) = [2, 0] integer, parameter :: VERSION_SUMMARY(2) = [5, 0] diff --git a/src/relaxng/tallies.rnc b/src/relaxng/tallies.rnc index 57f5f3747..4674fd4c0 100644 --- a/src/relaxng/tallies.rnc +++ b/src/relaxng/tallies.rnc @@ -32,15 +32,10 @@ element tallies { ) }* & - element tally { + element filter { (element id { xsd:int } | attribute id { xsd:int }) & - (element name { xsd:string { maxLength="52" } } | - attribute name { xsd:string { maxLength="52" } })? & - (element estimator { ( "analog" | "tracklength" | "collision" ) } | - attribute estimator { ( "analog" | "tracklength" | "collision" ) })? & - element filter { - ( - (element type { ( "cell" | "cellborn" | "material" | "universe" | + ( + ( (element type { ( "cell" | "cellborn" | "material" | "universe" | "surface" | "distribcell" | "mesh" | "energy" | "energyout" | "mu" | "polar" | "azimuthal" | "delayedgroup" | "energyfunction") } | attribute type { ( "cell" | "cellborn" | "material" | "universe" | @@ -57,7 +52,17 @@ element tallies { (element y { list { xsd:double+ } } | attribute y { list { xsd:double+ } }) ) - }* & + ) + }* & + + element tally { + (element id { xsd:int } | attribute id { xsd:int }) & + (element name { xsd:string { maxLength="52" } } | + attribute name { xsd:string { maxLength="52" } })? & + (element estimator { ( "analog" | "tracklength" | "collision" ) } | + attribute estimator { ( "analog" | "tracklength" | "collision" ) })? & + (element filters { list { xsd:int+ } } | + attribute filters { list { xsd:int+ } })? & element nuclides { list { xsd:string { maxLength = "12" }+ } }? & diff --git a/src/relaxng/tallies.rng b/src/relaxng/tallies.rng index fde06bac6..1c68e57e8 100644 --- a/src/relaxng/tallies.rng +++ b/src/relaxng/tallies.rng @@ -151,6 +151,120 @@ + + + + + + + + + + + + + + + + + cell + cellborn + material + universe + surface + distribcell + mesh + energy + energyout + mu + polar + azimuthal + delayedgroup + energyfunction + + + + + cell + cellborn + material + universe + surface + distribcell + mesh + energy + energyout + mu + polar + azimuthal + delayedgroup + energyfunction + + + + + + + + + + + + + + + + + + + + + + + + energyfunction + + + energyfunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -194,110 +308,24 @@ - - - - - - - - cell - cellborn - material - universe - surface - distribcell - mesh - energy - energyout - mu - polar - azimuthal - delayedgroup - energyfunction - - - - - cell - cellborn - material - universe - surface - distribcell - mesh - energy - energyout - mu - polar - azimuthal - delayedgroup - energyfunction - - - - - - - - - - - - - - - - - - - - - - - - energyfunction - - - energyfunction - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + +