From 5fb7d5c2386731ee4e28c1642544cf9515e3f615 Mon Sep 17 00:00:00 2001 From: Jon Walsh Date: Sat, 19 Jul 2014 16:09:35 -0600 Subject: [PATCH 1/6] implemented a unionized material energy grid option --- src/ace_header.F90 | 6 +- src/constants.F90 | 7 ++- src/cross_section.F90 | 84 ++++++++++++++++--------- src/energy_grid.F90 | 136 ++++++++++++++++++++++++++++------------ src/initialize.F90 | 4 +- src/input_xml.F90 | 8 ++- src/material_header.F90 | 7 +++ 7 files changed, 175 insertions(+), 77 deletions(-) diff --git a/src/ace_header.F90 b/src/ace_header.F90 index e5bf1bb3a4..480397a5e6 100644 --- a/src/ace_header.F90 +++ b/src/ace_header.F90 @@ -97,7 +97,7 @@ module ace_header ! Energy grid information integer :: n_grid ! # of nuclide grid points - integer, allocatable :: grid_index(:) ! pointers to union grid + integer, allocatable :: glob_grid_index(:) ! pointers to union grid real(8), allocatable :: energy(:) ! energy values corresponding to xs ! Microscopic cross sections @@ -337,8 +337,8 @@ module ace_header integer :: i ! Loop counter - if (allocated(this % grid_index)) & - deallocate(this % grid_index) + if (allocated(this % glob_grid_index)) & + deallocate(this % glob_grid_index) if (allocated(this % energy)) & deallocate(this % total, this % elastic, this % fission, & diff --git a/src/constants.F90 b/src/constants.F90 index 94edd9d2a2..4cedf798c5 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -382,9 +382,10 @@ module constants ! Energy grid methods integer, parameter :: & - GRID_NUCLIDE = 1, & ! non-unionized energy grid - GRID_UNION = 2, & ! union grid with pointers - GRID_LETHARGY = 3 ! lethargy mapping + GRID_NUCLIDE = 1, & ! non-unionized energy grid + GRID_GLOB_UNION = 2, & ! global union grid with pointers + GRID_MAT_UNION = 3, & ! material union grids with pointers + GRID_LETHARGY = 4 ! lethargy mapping ! Running modes integer, parameter :: & diff --git a/src/cross_section.F90 b/src/cross_section.F90 index 7426519cda..8fd2fac4d0 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -37,11 +37,11 @@ contains !$omp threadprivate(mat) ! Set all material macroscopic cross sections to zero - material_xs % total = ZERO - material_xs % elastic = ZERO - material_xs % absorption = ZERO - material_xs % fission = ZERO - material_xs % nu_fission = ZERO + material_xs % total = ZERO + material_xs % elastic = ZERO + material_xs % absorption = ZERO + material_xs % fission = ZERO + material_xs % nu_fission = ZERO material_xs % kappa_fission = ZERO ! Exit subroutine if material is void @@ -49,8 +49,9 @@ contains mat => materials(p % material) - ! Find energy index on unionized grid - if (grid_method == GRID_UNION) call find_energy_index(p % E) + ! Find energy index on global or material unionized grid + if (grid_method == GRID_GLOB_UNION .or. grid_method == GRID_MAT_UNION) & + & call find_energy_index(p % E, p % material) ! Determine if this material has S(a,b) tables check_sab = (mat % n_sab > 0) @@ -92,9 +93,9 @@ contains ! Calculate microscopic cross section for this nuclide if (p % E /= micro_xs(i_nuclide) % last_E) then - call calculate_nuclide_xs(i_nuclide, i_sab, p % E) + call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i) else if (i_sab /= micro_xs(i_nuclide) % last_index_sab) then - call calculate_nuclide_xs(i_nuclide, i_sab, p % E) + call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i) end if ! ======================================================================== @@ -135,34 +136,42 @@ contains ! given index in the nuclides array at the energy of the given particle !=============================================================================== - subroutine calculate_nuclide_xs(i_nuclide, i_sab, E) + subroutine calculate_nuclide_xs(i_nuclide, i_sab, E, i_mat, i_nuc_mat) integer, intent(in) :: i_nuclide ! index into nuclides array integer, intent(in) :: i_sab ! index into sab_tables array + integer, intent(in) :: i_mat ! index into materials array + integer, intent(in) :: i_nuc_mat ! index into nuclides array for a material real(8), intent(in) :: E ! energy integer :: i_grid ! index on nuclide energy grid real(8) :: f ! interp factor on nuclide energy grid - type(Nuclide), pointer, save :: nuc => null() + type(Nuclide), pointer, save :: nuc => null() + type(Material), pointer, save :: mat => null() !$omp threadprivate(nuc) - ! Set pointer to nuclide + ! Set pointer to nuclide and material nuc => nuclides(i_nuclide) + mat => materials(i_mat) ! Determine index on nuclide energy grid select case (grid_method) - case (GRID_UNION) - ! If we're using the unionized grid with pointers, finding the index on - ! the nuclide energy grid is as simple as looking up the pointer + ! If we're using a unionized grid with pointers, finding the index on + ! the nuclide energy grid is as simple as looking up the pointer + case (GRID_GLOB_UNION) - i_grid = nuc % grid_index(union_grid_index) + i_grid = nuc % glob_grid_index(union_grid_index) + + case (GRID_MAT_UNION) + + i_grid = mat % nuclide_grid_index(i_nuc_mat, union_grid_index) case (GRID_NUCLIDE) ! If we're not using the unionized grid, we have to do a binary search on ! the nuclide energy grid in order to determine which points to ! interpolate between - if (E < nuc % energy(1)) then + if (E <= nuc % energy(1)) then i_grid = 1 elseif (E > nuc % energy(nuc % n_grid)) then i_grid = nuc % n_grid - 1 @@ -465,19 +474,38 @@ contains ! energy !=============================================================================== - subroutine find_energy_index(E) + subroutine find_energy_index(E, i_mat) - real(8), intent(in) :: E ! energy of particle + real(8), intent(in) :: E ! energy of particle + integer, intent(in) :: i_mat ! material index + type(Material), pointer, save :: mat => null() ! pointer to current material - ! if particle's energy is outside of energy grid range, set to first or last - ! index. Otherwise, do a binary search through the union energy grid. - if (E < e_grid(1)) then - union_grid_index = 1 - elseif (E > e_grid(n_grid)) then - union_grid_index = n_grid - 1 - else - union_grid_index = binary_search(e_grid, n_grid, E) - end if + select case(grid_method) + case(GRID_GLOB_UNION) + ! if the energy is outside of energy grid range, set to first or last + ! index. Otherwise, do a binary search through the union energy grid. + if (E < e_grid(1)) then + union_grid_index = 1 + elseif (E > e_grid(n_grid)) then + union_grid_index = n_grid - 1 + else + union_grid_index = binary_search(e_grid, n_grid, E) + end if + + case(GRID_MAT_UNION) + mat => materials(i_mat) + + ! if the energy is outside of energy grid range, set to first or last + ! index. Otherwise, do a binary search through the union energy grid. + if (E <= mat % e_grid(1)) then + union_grid_index = 1 + elseif (E > mat % e_grid(mat % n_grid)) then + union_grid_index = mat % n_grid - 1 + else + union_grid_index = binary_search(mat % e_grid, mat % n_grid, E) + end if + + end select end subroutine find_energy_index diff --git a/src/energy_grid.F90 b/src/energy_grid.F90 index 66b95be0de..1c86982fcf 100644 --- a/src/energy_grid.F90 +++ b/src/energy_grid.F90 @@ -8,43 +8,75 @@ module energy_grid contains !=============================================================================== -! UNIONIZED_GRID creates a single unionized energy grid combined from each -! nuclide of each material. Right now, the grid for each nuclide is added into a -! linked list one at a time with an effective insertion sort. Could be done with -! a hash for all energy points and then a quicksort at the end (what hash -! function to use?) +! UNIONIZED_GRID creates a unionized energy grid, for the entire problem or for +! each material, composed of the grids from each nuclide in the entire problem, +! or each material, respectively. Right now, the grid for each nuclide is added +! into a linked list one at a time with an effective insertion sort. Could be +! done with a hash for all energy points and then a quicksort at the end (what +! hash function to use?) !=============================================================================== subroutine unionized_grid() integer :: i ! index in nuclides array + integer :: j ! index in materials array type(ListReal), pointer :: list => null() - type(Nuclide), pointer :: nuc => null() + type(Nuclide), pointer :: nuc => null() + type(Material), pointer :: mat => null() - message = "Creating unionized energy grid..." + message = "Creating unionized energy grid(s)..." call write_message(5) - ! Add grid points for each nuclide in the problem - do i = 1, n_nuclides_total - nuc => nuclides(i) - call add_grid_points(list, nuc % energy) - end do + select case(grid_method) + case(GRID_GLOB_UNION) + ! Add grid points for each nuclide in the problem + do i = 1, n_nuclides_total + nuc => nuclides(i) + call add_grid_points(list, nuc % energy) + end do - ! Set size of unionized energy grid - n_grid = list % size() + ! Set size of unionized energy grid + n_grid = list % size() - ! create allocated array from linked list - allocate(e_grid(n_grid)) - do i = 1, n_grid - e_grid(i) = list % get_item(i) - end do + ! create allocated array from linked list + allocate(e_grid(n_grid)) + do i = 1, n_grid + e_grid(i) = list % get_item(i) + end do - ! delete linked list and dictionary - call list % clear() - deallocate(list) + ! delete linked list and dictionary + call list % clear() + deallocate(list) - ! Set pointers to unionized energy grid for each nuclide - call grid_pointers() + ! Set pointers to unionized energy grid for each nuclide + call grid_pointers() + + case(GRID_MAT_UNION) + ! add grid points for each nuclide in the material + do j = 1, n_materials + mat => materials(j) + do i = 1, mat % n_nuclides + nuc => nuclides(mat % nuclide(i)) + call add_grid_points(list, nuc % energy) + end do + + ! set size of unionized material energy grid + mat % n_grid = list % size() + + ! create allocated array from linked list + allocate(mat % e_grid(mat % n_grid)) + do i = 1, mat % n_grid + mat % e_grid(i) = list % get_item(i) + end do + + ! delete linked list and dictionary + call list % clear() + deallocate(list) + end do + + ! Set pointers to unionized energy grid for each nuclide + call grid_pointers() + end select end subroutine unionized_grid @@ -117,34 +149,60 @@ contains !=============================================================================== ! GRID_POINTERS creates an array of pointers (ints) for each nuclide to link -! each point on the nuclide energy grid to one on the unionized energy grid +! each point on the nuclide energy grid to one on a unionized energy grid !=============================================================================== subroutine grid_pointers() integer :: i ! loop index for nuclides integer :: j ! loop index for nuclide energy grid + integer :: k ! loop index for materials integer :: index_e ! index on union energy grid real(8) :: union_energy ! energy on union grid real(8) :: energy ! energy on nuclide grid - type(Nuclide), pointer :: nuc => null() + type(Nuclide), pointer :: nuc => null() + type(Material), pointer :: mat => null() - do i = 1, n_nuclides_total - nuc => nuclides(i) - allocate(nuc % grid_index(n_grid)) + select case(grid_method) + case(GRID_GLOB_UNION) + do i = 1, n_nuclides_total + nuc => nuclides(i) + allocate(nuc % glob_grid_index(n_grid)) - index_e = 1 - energy = nuc % energy(index_e) + index_e = 1 + energy = nuc % energy(index_e) - do j = 1, n_grid - union_energy = e_grid(j) - if (union_energy >= energy .and. index_e < nuc % n_grid) then - index_e = index_e + 1 - energy = nuc % energy(index_e) - end if - nuc % grid_index(j) = index_e - 1 + do j = 1, n_grid + union_energy = e_grid(j) + if (union_energy >= energy .and. index_e < nuc % n_grid) then + index_e = index_e + 1 + energy = nuc % energy(index_e) + end if + nuc % glob_grid_index(j) = index_e - 1 + end do end do - end do + + case(GRID_MAT_UNION) + do k = 1, n_materials + mat => materials(k) + allocate(mat % nuclide_grid_index(mat % n_nuclides, mat % n_grid)) + do i = 1, mat % n_nuclides + nuc => nuclides(mat % nuclide(i)) + + index_e = 1 + energy = nuc % energy(index_e) + + do j = 1, mat % n_grid + union_energy = mat % e_grid(j) + if (union_energy >= energy .and. index_e < nuc % n_grid) then + index_e = index_e + 1 + energy = nuc % energy(index_e) + end if + mat % nuclide_grid_index(i,j) = index_e - 1 + end do + end do + end do + end select end subroutine grid_pointers diff --git a/src/initialize.F90 b/src/initialize.F90 index c14a8a02a7..bfcd1cc5d7 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -105,7 +105,9 @@ contains call time_read_xs % stop() ! Construct unionized energy grid from cross-sections - if (grid_method == GRID_UNION) then + if (grid_method == GRID_NUCLIDE) then + continue + else call time_unionize % start() call unionized_grid() call time_unionize % stop() diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 46461b78da..b6523f6eab 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -213,13 +213,15 @@ contains if (check_for_node(doc, "energy_grid")) then call get_node_value(doc, "energy_grid", temp_str) else - temp_str = 'union' + temp_str = 'global-union' end if select case (trim(temp_str)) case ('nuclide') grid_method = GRID_NUCLIDE - case ('union') - grid_method = GRID_UNION + case ('global-union') + grid_method = GRID_GLOB_UNION + case ('material-union') + grid_method = GRID_MAT_UNION case ('lethargy') message = "Lethargy mapped energy grid not yet supported." call fatal_error() diff --git a/src/material_header.F90 b/src/material_header.F90 index cbfd917498..6b6bb593eb 100644 --- a/src/material_header.F90 +++ b/src/material_header.F90 @@ -13,6 +13,13 @@ module material_header real(8) :: density ! total atom density in atom/b-cm real(8), allocatable :: atom_density(:) ! nuclide atom density in atom/b-cm + ! Energy grid information + integer :: n_grid ! # of union material grid points + real(8), allocatable :: e_grid(:) ! union material grid energies + + ! Unionized energy grid information + integer, allocatable :: nuclide_grid_index(:,:) ! nuclide e_grid pointers + ! S(a,b) data references integer :: n_sab = 0 ! number of S(a,b) tables integer, allocatable :: i_sab_nuclides(:) ! index of corresponding nuclide From 69f378518c55cdc81744690322cc96ab205f1dbd Mon Sep 17 00:00:00 2001 From: walshjon Date: Thu, 13 Nov 2014 20:10:57 -0800 Subject: [PATCH 2/6] remove unnecessary critical blocks to speed up threading --- src/cross_section.F90 | 3 ++- src/energy_grid.F90 | 7 ++++--- src/initialize.F90 | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cross_section.F90 b/src/cross_section.F90 index e83e1303a4..370c5c3630 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -149,7 +149,7 @@ contains real(8) :: f ! interp factor on nuclide energy grid type(Nuclide), pointer, save :: nuc => null() type(Material), pointer, save :: mat => null() -!$omp threadprivate(nuc) +!$omp threadprivate(nuc, mat) ! Set pointer to nuclide and material nuc => nuclides(i_nuclide) @@ -515,6 +515,7 @@ contains real(8), intent(in) :: E ! energy of particle integer, intent(in) :: i_mat ! material index type(Material), pointer, save :: mat => null() ! pointer to current material +!$omp threadprivate(mat) select case(grid_method) case(GRID_GLOB_UNION) diff --git a/src/energy_grid.F90 b/src/energy_grid.F90 index 7ea9d34ff4..b168d17ff1 100644 --- a/src/energy_grid.F90 +++ b/src/energy_grid.F90 @@ -22,9 +22,10 @@ contains integer :: i ! index in nuclides array integer :: j ! index in materials array - type(ListReal), pointer :: list => null() - type(Nuclide), pointer :: nuc => null() - type(Material), pointer :: mat => null() + type(ListReal), pointer, save :: list => null() + type(Nuclide), pointer, save :: nuc => null() + type(Material), pointer, save :: mat => null() +!$omp threadprivate(list, nuc, mat) call write_message("Creating unionized energy grid...", 5) diff --git a/src/initialize.F90 b/src/initialize.F90 index 34272fe882..f15541df0f 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -113,7 +113,9 @@ contains continue else call time_unionize % start() +!$omp critical call unionized_grid() +!$omp end critical call time_unionize % stop() end if From 3858f412374c1200199262633af525179c599eee Mon Sep 17 00:00:00 2001 From: walshjon Date: Thu, 19 Mar 2015 18:19:37 -0700 Subject: [PATCH 3/6] cleaned up merge of mit-crpg/openmc/develop --- src/ace_header.F90 | 3 -- src/constants.F90 | 2 +- src/cross_section.F90 | 3 ++ src/energy_grid.F90 | 71 ++++++++++++++++++++++++++++++++++++++++++- src/global.F90 | 1 + src/initialize.F90 | 4 +-- 6 files changed, 77 insertions(+), 7 deletions(-) diff --git a/src/ace_header.F90 b/src/ace_header.F90 index 655b1480ec..7753f4734a 100644 --- a/src/ace_header.F90 +++ b/src/ace_header.F90 @@ -372,9 +372,6 @@ module ace_header integer :: i ! Loop counter - if (allocated(this % glob_grid_index)) & - deallocate(this % glob_grid_index) - if (allocated(this % energy)) & deallocate(this % energy, this % total, this % elastic, & & this % fission, this % nu_fission, this % absorption) diff --git a/src/constants.F90 b/src/constants.F90 index bd8d805783..85976c00ac 100644 --- a/src/constants.F90 +++ b/src/constants.F90 @@ -368,7 +368,7 @@ module constants ! Energy grid methods integer, parameter :: & - GRID_NUCLIDE = 1, & ! non-unionized energy grid + GRID_NUCLIDE = 1, & ! unique energy grid for each nuclide GRID_MAT_UNION = 2, & ! material union grids with pointers GRID_LOGARITHM = 3 ! lethargy mapping diff --git a/src/cross_section.F90 b/src/cross_section.F90 index c667dd2a52..8a6981d223 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -15,6 +15,9 @@ module cross_section implicit none save + integer :: union_grid_index +!$omp threadprivate(union_grid_index) + contains !=============================================================================== diff --git a/src/energy_grid.F90 b/src/energy_grid.F90 index 5ac8f561ed..676875a5b4 100644 --- a/src/energy_grid.F90 +++ b/src/energy_grid.F90 @@ -1,6 +1,9 @@ module energy_grid use global + use list_header, only: ListReal + use output, only: write_message + implicit none @@ -56,7 +59,6 @@ contains call grid_pointers() end subroutine unionized_grid ->>>>>>> mit-crpg/openmc/develop !=============================================================================== ! LOGARITHMIC_GRID determines a logarithmic mapping for energies to bounding @@ -107,6 +109,73 @@ contains end subroutine logarithmic_grid +!=============================================================================== +! ADD_GRID_POINTS adds energy points from the 'energy' array into a linked list +! of points already stored from previous arrays. +!=============================================================================== + + subroutine add_grid_points(list, energy) + + type(ListReal), pointer :: list + real(8), intent(in) :: energy(:) + + integer :: i ! index in energy array + integer :: n ! size of energy array + integer :: current ! current index + real(8) :: E ! actual energy value + + i = 1 + n = size(energy) + + ! If the original list is empty, we need to allocate the first element and + ! store first energy point + if (.not. associated(list)) then + allocate(list) + do i = 1, n + call list % append(energy(i)) + end do + return + end if + + ! Set current index to beginning of the list + current = 1 + + do while (i <= n) + E = energy(i) + + ! If we've reached the end of the grid energy list, add the remaining + ! energy points to the end + if (current > list % size()) then + ! Finish remaining energies + do while (i <= n) + call list % append(energy(i)) + i = i + 1 + end do + exit + end if + + if (E < list % get_item(current)) then + + ! Insert new energy in this position + call list % insert(current, E) + + ! Advance index in linked list and in new energy grid + i = i + 1 + current = current + 1 + + elseif (E == list % get_item(current)) then + ! Found the exact same energy, no need to store duplicates so just + ! skip and move to next index + i = i + 1 + current = current + 1 + else + current = current + 1 + end if + + end do + + end subroutine add_grid_points + !=============================================================================== ! GRID_POINTERS creates an array of pointers (ints) for each nuclide to link ! each point on the nuclide energy grid to one on a unionized energy grid diff --git a/src/global.F90 b/src/global.F90 index 004c43746e..06be1c992f 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -218,6 +218,7 @@ module global type(Timer) :: time_total ! timer for total run type(Timer) :: time_initialize ! timer for initialization type(Timer) :: time_read_xs ! timer for reading cross sections + type(Timer) :: time_unionize ! timer for material xs-energy grid union type(Timer) :: time_bank ! timer for fission bank synchronization type(Timer) :: time_bank_sample ! timer for fission bank sampling type(Timer) :: time_bank_sendrecv ! timer for fission bank SEND/RECV diff --git a/src/initialize.F90 b/src/initialize.F90 index 8c5079c789..29ed52aa0b 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -4,7 +4,7 @@ module initialize use bank_header, only: Bank use constants use dict_header, only: DictIntInt, ElemKeyValueII - use energy_grid, only: logarithmic_grid, grid_method + use energy_grid, only: logarithmic_grid, grid_method, unionized_grid use error, only: fatal_error, warning use geometry, only: neighbor_lists use geometry_header, only: Cell, Universe, Lattice, RectLattice, HexLattice,& @@ -121,7 +121,7 @@ contains call time_unionize % stop() case (GRID_LOGARITHM) call logarithmic_grid() - end if + end select ! Allocate and setup tally stride, matching_bins, and tally maps call configure_tallies() From 1e2f803776e525ed5f20821b417262603754f2ad Mon Sep 17 00:00:00 2001 From: walshjon Date: Thu, 26 Mar 2015 13:19:48 -0700 Subject: [PATCH 4/6] add test, address review comments --- src/cross_section.F90 | 2 +- src/initialize.F90 | 2 - src/input_xml.F90 | 5 +- tests/test_union_energy_grids/geometry.xml | 8 +++ tests/test_union_energy_grids/materials.xml | 11 ++++ tests/test_union_energy_grids/results.py | 25 ++++++++ .../test_union_energy_grids/results_true.dat | 2 + tests/test_union_energy_grids/settings.xml | 18 ++++++ .../test_union_energy_grids.py | 59 +++++++++++++++++++ 9 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 tests/test_union_energy_grids/geometry.xml create mode 100644 tests/test_union_energy_grids/materials.xml create mode 100644 tests/test_union_energy_grids/results.py create mode 100644 tests/test_union_energy_grids/results_true.dat create mode 100644 tests/test_union_energy_grids/settings.xml create mode 100644 tests/test_union_energy_grids/test_union_energy_grids.py diff --git a/src/cross_section.F90 b/src/cross_section.F90 index 8a6981d223..dce4d75f32 100644 --- a/src/cross_section.F90 +++ b/src/cross_section.F90 @@ -53,7 +53,7 @@ contains ! Find energy index on global or material unionized grid if (grid_method == GRID_MAT_UNION) & - & call find_energy_index(p % E, p % material) + call find_energy_index(p % E, p % material) ! Determine if this material has S(a,b) tables check_sab = (mat % n_sab > 0) diff --git a/src/initialize.F90 b/src/initialize.F90 index 29ed52aa0b..51dbf5ed52 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -115,9 +115,7 @@ contains continue case (GRID_MAT_UNION) call time_unionize % start() -!$omp critical call unionized_grid() -!$omp end critical call time_unionize % stop() case (GRID_LOGARITHM) call logarithmic_grid() diff --git a/src/input_xml.F90 b/src/input_xml.F90 index 0ae299aa4e..dd28cd9610 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -213,8 +213,11 @@ contains select case (trim(temp_str)) case ('nuclide') grid_method = GRID_NUCLIDE - case ('material-union') + case ('material-union', 'union') grid_method = GRID_MAT_UNION + if (trim(temp_str) == 'union') & + call warning('Energy grids will be unionized by material. Global& + & energy grid unionization is no longer an allowed option.') case ('logarithm', 'logarithmic', 'log') grid_method = GRID_LOGARITHM case default diff --git a/tests/test_union_energy_grids/geometry.xml b/tests/test_union_energy_grids/geometry.xml new file mode 100644 index 0000000000..612e46132e --- /dev/null +++ b/tests/test_union_energy_grids/geometry.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/test_union_energy_grids/materials.xml b/tests/test_union_energy_grids/materials.xml new file mode 100644 index 0000000000..45ccc65540 --- /dev/null +++ b/tests/test_union_energy_grids/materials.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/tests/test_union_energy_grids/results.py b/tests/test_union_energy_grids/results.py new file mode 100644 index 0000000000..be13ee66f1 --- /dev/null +++ b/tests/test_union_energy_grids/results.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +import sys + +# import statepoint +sys.path.insert(0, '../../src/utils') +import statepoint + +# read in statepoint file +if len(sys.argv) > 1: + sp = statepoint.StatePoint(sys.argv[1]) +else: + sp = statepoint.StatePoint('statepoint.10.binary') +sp.read_results() + +# set up output string +outstr = '' + +# write out k-combined +outstr += 'k-combined:\n' +outstr += "{0:12.6E} {1:12.6E}\n".format(sp.k_combined[0], sp.k_combined[1]) + +# write results to file +with open('results_test.dat','w') as fh: + fh.write(outstr) diff --git a/tests/test_union_energy_grids/results_true.dat b/tests/test_union_energy_grids/results_true.dat new file mode 100644 index 0000000000..05cda2e980 --- /dev/null +++ b/tests/test_union_energy_grids/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +3.215828E-01 2.966835E-03 diff --git a/tests/test_union_energy_grids/settings.xml b/tests/test_union_energy_grids/settings.xml new file mode 100644 index 0000000000..1eb22241cc --- /dev/null +++ b/tests/test_union_energy_grids/settings.xml @@ -0,0 +1,18 @@ + + + + union + + + 10 + 5 + 1000 + + + + + -4 -4 -4 4 4 4 + + + + diff --git a/tests/test_union_energy_grids/test_union_energy_grids.py b/tests/test_union_energy_grids/test_union_energy_grids.py new file mode 100644 index 0000000000..6fdbf87459 --- /dev/null +++ b/tests/test_union_energy_grids/test_union_energy_grids.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +import os +from subprocess import Popen, STDOUT, PIPE, call +import filecmp +import glob +from optparse import OptionParser + +parser = OptionParser() +parser.add_option('--mpi_exec', dest='mpi_exec', default='') +parser.add_option('--mpi_np', dest='mpi_np', default='3') +parser.add_option('--exe', dest='exe') +(opts, args) = parser.parse_args() +cwd = os.getcwd() + +def test_run(): + if opts.mpi_exec != '': + proc = Popen([opts.mpi_exec, '-np', opts.mpi_np, opts.exe, cwd], + stderr=STDOUT, stdout=PIPE) + else: + proc = Popen([opts.exe, cwd], stderr=STDOUT, stdout=PIPE) + print(proc.communicate()[0]) + returncode = proc.returncode + assert returncode == 0, 'OpenMC did not exit successfully.' + +def test_created_statepoint(): + statepoint = glob.glob(os.path.join(cwd, 'statepoint.10.*')) + assert len(statepoint) == 1, 'Either multiple or no statepoint files exist.' + assert statepoint[0].endswith('binary') or statepoint[0].endswith('h5'),\ + 'Statepoint file is not a binary or hdf5 file.' + +def test_results(): + statepoint = glob.glob(os.path.join(cwd, 'statepoint.10.*')) + call(['python', 'results.py', statepoint[0]]) + compare = filecmp.cmp('results_test.dat', 'results_true.dat') + if not compare: + os.rename('results_test.dat', 'results_error.dat') + assert compare, 'Results do not agree.' + +def teardown(): + output = glob.glob(os.path.join(cwd, 'statepoint.10.*')) + output.append(os.path.join(cwd, 'results_test.dat')) + for f in output: + if os.path.exists(f): + os.remove(f) + +if __name__ == '__main__': + + # test for openmc executable + if opts.exe is None: + raise Exception('Must specify OpenMC executable from command line with --exe.') + + # run tests + try: + test_run() + test_created_statepoint() + test_results() + finally: + teardown() From 49b09c00dae175e57a701c045a577470d69c816b Mon Sep 17 00:00:00 2001 From: Jon Walsh Date: Thu, 16 Apr 2015 01:42:58 -0400 Subject: [PATCH 5/6] update schema for settings.xml --- src/relaxng/settings.rnc | 2 +- src/relaxng/settings.rng | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/relaxng/settings.rnc b/src/relaxng/settings.rnc index a7b92e1738..092bf9983c 100644 --- a/src/relaxng/settings.rnc +++ b/src/relaxng/settings.rnc @@ -27,7 +27,7 @@ element settings { (element weight_avg { xsd:double } | attribute weight_avg { xsd:double })? }? & - element energy_grid { ( "nuclide" | "log" | "logarithm" | "logarithmic" ) }? & + element energy_grid { ( "nuclide" | "log" | "logarithm" | "logarithmic" | "material-union" | "union" ) }? & element entropy { (element dimension { list { xsd:int+ } } | diff --git a/src/relaxng/settings.rng b/src/relaxng/settings.rng index 02dba3688e..10770f80cc 100644 --- a/src/relaxng/settings.rng +++ b/src/relaxng/settings.rng @@ -106,6 +106,8 @@ log logarithm logarithmic + material-union + union From 057d65c2b1a00cdfc0f298e3ceea7c47904c6ba5 Mon Sep 17 00:00:00 2001 From: Jon Walsh Date: Thu, 16 Apr 2015 01:54:18 -0400 Subject: [PATCH 6/6] update documentation to mention energy grids unionized by material --- docs/source/usersguide/input.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 79d66d2869..2ca93e3288 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -174,11 +174,15 @@ should be performed. It has the following attributes/sub-elements: ------------------------- The ```` element determines the treatment of the energy grid during -a simulation. The valid options are "nuclide" and "logarithm". Setting this -element to "nuclide" will cause OpenMC to use a nuclide's energy grid when -determining what points to interpolate between for determining cross sections -(i.e. non-unionized energy grid). Setting this element to "logarithm" causes -OpenMC to use a logarithmic mapping technique described in LA-UR-14-24530_. +a simulation. The valid options are "nuclide", "logarithm", and +"material-union". Setting this element to "nuclide" will cause OpenMC to use a +nuclide's energy grid when determining what points to interpolate between for +determining cross sections (i.e. non-unionized energy grid). Setting this +element to "logarithm" causes OpenMC to use a logarithmic mapping technique +described in LA-UR-14-24530_. Setting this element to "material-union" will +cause OpenMC to create energy grids that are unionized material-by-material and +use these grids when determining the energy-cross section pairs to interpolate +cross section values between. *Default*: logarithm