From 6c4891d59187a313deaa07ef3ed9b2ff3b689c9a Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sun, 14 Oct 2018 13:01:57 -0400 Subject: [PATCH] Move UniverseFilter to C++ --- .../openmc/tallies/tally_filter_material.h | 1 + .../openmc/tallies/tally_filter_universe.h | 84 ++++++++++++++ src/geometry_header.F90 | 2 - src/input_xml.F90 | 2 - src/tallies/tally_filter.cpp | 3 + src/tallies/tally_filter_universe.F90 | 106 +----------------- 6 files changed, 89 insertions(+), 109 deletions(-) create mode 100644 include/openmc/tallies/tally_filter_universe.h diff --git a/include/openmc/tallies/tally_filter_material.h b/include/openmc/tallies/tally_filter_material.h index 3fd5893759..92f2df640c 100644 --- a/include/openmc/tallies/tally_filter_material.h +++ b/include/openmc/tallies/tally_filter_material.h @@ -1,6 +1,7 @@ #ifndef OPENMC_TALLY_FILTER_MATERIAL_H #define OPENMC_TALLY_FILTER_MATERIAL_H +#include #include #include #include diff --git a/include/openmc/tallies/tally_filter_universe.h b/include/openmc/tallies/tally_filter_universe.h new file mode 100644 index 0000000000..c61301c369 --- /dev/null +++ b/include/openmc/tallies/tally_filter_universe.h @@ -0,0 +1,84 @@ +#ifndef OPENMC_TALLY_FILTER_UNIVERSE_H +#define OPENMC_TALLY_FILTER_UNIVERSE_H + +#include +#include +#include +#include + +#include "openmc/cell.h" +#include "openmc/error.h" +#include "openmc/tallies/tally_filter.h" + + +namespace openmc { + +class UniverseFilter : public TallyFilter +{ +public: + virtual std::string type() const override {return "universe";} + + virtual ~UniverseFilter() override = default; + + virtual void + from_xml(pugi::xml_node node) override + { + universes_ = get_node_array(node, "bins"); + n_bins_ = universes_.size(); + } + + virtual void + initialize() override + { + for (auto& u : universes_) { + auto search = universe_map.find(u); + if (search != universe_map.end()) { + u = search->second; + } else { + std::stringstream err_msg; + err_msg << "Could not find universe " << u + << " specified on tally filter."; + fatal_error(err_msg); + } + } + + for (int i = 0; i < universes_.size(); i++) { + map_[universes_[i]] = i; + } + } + + virtual void + get_all_bins(Particle* p, int estimator, TallyFilterMatch& match) + const override + { + for (int i = 0; i < p->n_coord; i++) { + auto search = map_.find(p->coord[i].universe); + if (search != map_.end()) { + // TODO: off-by-one + match.bins.push_back(search->second + 1); + match.weights.push_back(1); + } + } + } + + virtual void + to_statepoint(hid_t filter_group) const override + { + TallyFilter::to_statepoint(filter_group); + std::vector universe_ids; + for (auto u : universes_) universe_ids.push_back(universes[u]->id_); + write_dataset(filter_group, "bins", universe_ids); + } + + virtual std::string + text_label(int bin) const override + { + return "Universe " + std::to_string(universes[universes_[bin-1]]->id_); + } + + std::vector universes_; + std::unordered_map map_; +}; + +} // namespace openmc +#endif // OPENMC_TALLY_FILTER_UNIVERSE_H diff --git a/src/geometry_header.F90 b/src/geometry_header.F90 index 89cfbcf2a7..9af1fcbaa0 100644 --- a/src/geometry_header.F90 +++ b/src/geometry_header.F90 @@ -153,7 +153,6 @@ module geometry_header ! Dictionaries which map user IDs to indices in the global arrays type(DictIntInt) :: cell_dict - type(DictIntInt) :: universe_dict type(DictIntInt) :: lattice_dict contains @@ -305,7 +304,6 @@ contains if (allocated(lattices)) deallocate(lattices) call cell_dict % clear() - call universe_dict % clear() call lattice_dict % clear() end subroutine free_memory_geometry diff --git a/src/input_xml.F90 b/src/input_xml.F90 index e6ebe30587..8a3682c055 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -391,7 +391,6 @@ contains if (.not. cells_in_univ_dict % has(univ_id)) then n_universes = n_universes + 1 n_cells_in_univ = 1 - call universe_dict % set(univ_id, n_universes) call univ_ids % push_back(univ_id) else n_cells_in_univ = 1 + cells_in_univ_dict % get(univ_id) @@ -561,7 +560,6 @@ contains if (.not. cells_in_univ_dict % has(univ_id)) then n_universes = n_universes + 1 n_cells_in_univ = 1 - call universe_dict % set(univ_id, n_universes - 1) call univ_ids % push_back(univ_id) else n_cells_in_univ = 1 + cells_in_univ_dict % get(univ_id) diff --git a/src/tallies/tally_filter.cpp b/src/tallies/tally_filter.cpp index dfe241cd54..c5d5600a1c 100644 --- a/src/tallies/tally_filter.cpp +++ b/src/tallies/tally_filter.cpp @@ -13,6 +13,7 @@ #include "openmc/tallies/tally_filter_meshsurface.h" #include "openmc/tallies/tally_filter_mu.h" #include "openmc/tallies/tally_filter_polar.h" +#include "openmc/tallies/tally_filter_universe.h" namespace openmc { @@ -104,6 +105,8 @@ extern "C" { tally_filters.push_back(new MuFilter()); } else if (type_ == "polar") { tally_filters.push_back(new PolarFilter()); + } else if (type_ == "universe") { + tally_filters.push_back(new UniverseFilter()); } else { return nullptr; } diff --git a/src/tallies/tally_filter_universe.F90 b/src/tallies/tally_filter_universe.F90 index bd42d494a0..2f3d5011c9 100644 --- a/src/tallies/tally_filter_universe.F90 +++ b/src/tallies/tally_filter_universe.F90 @@ -1,118 +1,14 @@ module tally_filter_universe - use, intrinsic :: ISO_C_BINDING - - use constants, only: ONE, MAX_LINE_LEN - use dict_header, only: EMPTY - use error, only: fatal_error - use hdf5_interface - use geometry_header - use particle_header, only: Particle - use string, only: to_str use tally_filter_header - use xml_interface implicit none - private !=============================================================================== ! UNIVERSEFILTER specifies which geometric universes tally events reside in. !=============================================================================== - type, public, extends(TallyFilter) :: UniverseFilter - integer, allocatable :: universes(:) - type(DictIntInt) :: map - contains - procedure :: from_xml - procedure :: get_all_bins => get_all_bins_universe - procedure :: to_statepoint => to_statepoint_universe - procedure :: text_label => text_label_universe - procedure :: initialize => initialize_universe + type, extends(CppTallyFilter) :: UniverseFilter end type UniverseFilter -contains - - subroutine from_xml(this, node) - class(UniverseFilter), intent(inout) :: this - type(XMLNode), intent(in) :: node - - integer :: n - - n = node_word_count(node, "bins") - - ! Allocate and store bins - this % n_bins = n - allocate(this % universes(n)) - call get_node_array(node, "bins", this % universes) - end subroutine from_xml - - subroutine get_all_bins_universe(this, p, estimator, match) - class(UniverseFilter), intent(in) :: this - type(Particle), intent(in) :: p - integer, intent(in) :: estimator - type(TallyFilterMatch), intent(inout) :: match - - integer :: i - integer :: val - - ! Iterate over coordinate levels to see which universes match - do i = 1, p % n_coord - val = this % map % get(p % coord(i) % universe) - if (val /= EMPTY) then - call match % bins_push_back(val) - call match % weights_push_back(ONE) - end if - end do - - end subroutine get_all_bins_universe - - subroutine to_statepoint_universe(this, filter_group) - class(UniverseFilter), intent(in) :: this - integer(HID_T), intent(in) :: filter_group - - integer :: i - integer, allocatable :: universe_ids(:) - - call write_dataset(filter_group, "type", "universe") - call write_dataset(filter_group, "n_bins", this % n_bins) - - allocate(universe_ids(size(this % universes))) - do i = 1, size(this % universes) - universe_ids(i) = universe_id(this % universes(i)) - end do - call write_dataset(filter_group, "bins", universe_ids) - end subroutine to_statepoint_universe - - subroutine initialize_universe(this) - class(UniverseFilter), intent(inout) :: this - - integer :: i, id - integer :: val - - ! Convert ids to indices. - do i = 1, this % n_bins - id = this % universes(i) - val = universe_dict % get(id) - if (val /= EMPTY) then - this % universes(i) = val - else - call fatal_error("Could not find universe " // trim(to_str(id)) & - &// " specified on a tally filter.") - end if - end do - - ! Generate mapping from universe indices to filter bins. - do i = 1, this % n_bins - call this % map % set(this % universes(i), i) - end do - end subroutine initialize_universe - - function text_label_universe(this, bin) result(label) - class(UniverseFilter), intent(in) :: this - integer, intent(in) :: bin - character(MAX_LINE_LEN) :: label - - label = "Universe " // to_str(universe_id(this % universes(bin))) - end function text_label_universe - end module tally_filter_universe