diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fbaf3c2ef..90fd3ced4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -378,6 +378,7 @@ set(LIBOPENMC_FORTRAN_SRC src/volume_header.F90 src/xml_interface.F90 src/tallies/tally.F90 + src/tallies/tally_derivative_header.F90 src/tallies/tally_filter.F90 src/tallies/tally_filter_header.F90 src/tallies/tally_filter_azimuthal.F90 diff --git a/src/global.F90 b/src/global.F90 index 28b035e4b2..09652f294a 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -16,6 +16,7 @@ module global use surface_header use tally_filter_header use tally_header + use tally_derivative_header use timer_header use trigger_header use volume_header diff --git a/src/input_xml.F90 b/src/input_xml.F90 index b818e5bc0d..71c699c894 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2493,7 +2493,6 @@ contains type(XMLNode) :: node_tal type(XMLNode) :: node_filt type(XMLNode) :: node_trigger - type(XMLNode) :: node_deriv type(XMLNode), allocatable :: node_mesh_list(:) type(XMLNode), allocatable :: node_tal_list(:) type(XMLNode), allocatable :: node_filt_list(:) @@ -2582,75 +2581,10 @@ contains ! Read derivative attributes. do i = 1, size(node_deriv_list) - associate(deriv => tally_derivs(i)) - ! Get pointer to derivative node. - node_deriv = node_deriv_list(i) + call tally_derivs(i) % from_xml(node_deriv_list(i)) - ! Copy the derivative id. - if (check_for_node(node_deriv, "id")) then - call get_node_value(node_deriv, "id", deriv % id) - else - call fatal_error("Must specify an ID for elements in the& - & tally XML file") - end if - - ! Make sure the id is > 0. - if (deriv % id <= 0) then - call fatal_error(" IDs must be an integer greater than & - &zero") - end if - - ! Make sure this id has not already been used. - do j = 1, i-1 - if (tally_derivs(j) % id == deriv % id) then - call fatal_error("Two or more 's use the same unique & - &ID: " // trim(to_str(deriv % id))) - end if - end do - - ! Read the independent variable name. - temp_str = "" - call get_node_value(node_deriv, "variable", temp_str) - temp_str = to_lower(temp_str) - - select case(temp_str) - - case("density") - deriv % variable = DIFF_DENSITY - call get_node_value(node_deriv, "material", deriv % diff_material) - - case("nuclide_density") - deriv % variable = DIFF_NUCLIDE_DENSITY - call get_node_value(node_deriv, "material", deriv % diff_material) - - call get_node_value(node_deriv, "nuclide", word) - word = trim(to_lower(word)) - pair_list => nuclide_dict % keys() - do while (associated(pair_list)) - if (starts_with(pair_list % key, word)) then - word = pair_list % key(1:150) - exit - end if - - ! Advance to next - pair_list => pair_list % next - end do - - ! Check if no nuclide was found - if (.not. associated(pair_list)) then - call fatal_error("Could not find the nuclide " & - // trim(word) // " specified in derivative " & - // trim(to_str(deriv % id)) // " in any material.") - end if - deallocate(pair_list) - - deriv % diff_nuclide = nuclide_dict % get_key(word) - - case("temperature") - deriv % variable = DIFF_TEMPERATURE - call get_node_value(node_deriv, "material", deriv % diff_material) - end select - end associate + ! Update tally derivative dictionary + call tally_deriv_dict % add_key(tally_derivs(i) % id, i) end do ! ========================================================================== @@ -2693,13 +2627,11 @@ contains if (.not. check_for_node(node_filt, "bins")) then 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", "cellfrom", "surface", "delayedgroup") if (.not. check_for_node(node_filt, "bins")) then 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 ! Allocate according to the filter type diff --git a/src/tallies/tally_derivative_header.F90 b/src/tallies/tally_derivative_header.F90 new file mode 100644 index 0000000000..004db98bad --- /dev/null +++ b/src/tallies/tally_derivative_header.F90 @@ -0,0 +1,91 @@ +module tally_derivative_header + + use constants + use dict_header, only: DictIntInt + use error, only: fatal_error + use nuclide_header, only: nuclide_dict + use string, only: to_str, to_lower + use xml_interface + + implicit none + private + +!=============================================================================== +! TALLYDERIVATIVE describes a first-order derivative that can be applied to +! tallies. +!=============================================================================== + + type, public :: TallyDerivative + integer :: id + integer :: variable + integer :: diff_material + integer :: diff_nuclide + real(8) :: flux_deriv + contains + procedure :: from_xml + end type TallyDerivative + + type(TallyDerivative), public, allocatable :: tally_derivs(:) +!$omp threadprivate(tally_derivs) + + ! Dictionary that maps user IDs to indices in 'tally_derivs' + type(DictIntInt), public :: tally_deriv_dict + +contains + + subroutine from_xml(this, node) + class(TallyDerivative), intent(inout) :: this + type(XMLNode), intent(in) :: node + + character(MAX_WORD_LEN) :: temp_str + character(MAX_WORD_LEN) :: word + + ! Copy the derivative id. + if (check_for_node(node, "id")) then + call get_node_value(node, "id", this % id) + else + call fatal_error("Must specify an ID for elements in the& + & tally XML file") + end if + + ! Make sure the id is > 0. + if (this % id <= 0) then + call fatal_error(" IDs must be an integer greater than & + &zero") + end if + + ! Make sure this id has not already been used. + if (tally_deriv_dict % has_key(this % id)) then + call fatal_error("Two or more 's use the same unique & + &ID: " // trim(to_str(this % id))) + end if + + ! Read the independent variable name. + call get_node_value(node, "variable", temp_str) + temp_str = to_lower(temp_str) + + select case(temp_str) + case("density") + this % variable = DIFF_DENSITY + + case("nuclide_density") + this % variable = DIFF_NUCLIDE_DENSITY + + call get_node_value(node, "nuclide", word) + word = trim(to_lower(word)) + if (.not. nuclide_dict % has_key(word)) then + call fatal_error("Could not find the nuclide " & + // trim(word) // " specified in derivative " & + // trim(to_str(this % id)) // " in any material.") + end if + this % diff_nuclide = nuclide_dict % get_key(word) + + case("temperature") + this % variable = DIFF_TEMPERATURE + end select + + call get_node_value(node, "material", this % diff_material) + + end subroutine from_xml + +end module tally_derivative_header diff --git a/src/tallies/tally_header.F90 b/src/tallies/tally_header.F90 index 9c6e69f84c..f053e6cac8 100644 --- a/src/tallies/tally_header.F90 +++ b/src/tallies/tally_header.F90 @@ -30,19 +30,6 @@ module tally_header public :: openmc_tally_set_nuclides public :: openmc_tally_set_scores -!=============================================================================== -! TALLYDERIVATIVE describes a first-order derivative that can be applied to -! tallies. -!=============================================================================== - - type, public :: TallyDerivative - integer :: id - integer :: variable - integer :: diff_material - integer :: diff_nuclide - real(8) :: flux_deriv - end type TallyDerivative - !=============================================================================== ! TALLYOBJECT describes a user-specified tally. The region of phase space to ! tally in is given by the TallyFilters and the results are stored in a @@ -124,8 +111,6 @@ module tally_header integer(C_INT32_T), public, bind(C) :: n_tallies = 0 ! # of tallies type(TallyContainer), public, allocatable, target :: tallies(:) - type(TallyDerivative), public, allocatable :: tally_derivs(:) -!$omp threadprivate(tally_derivs) ! Dictionary that maps user IDs to indices in 'tallies' type(DictIntInt), public :: tally_dict