Move UniverseFilter to C++

This commit is contained in:
Sterling Harper 2018-10-14 13:01:57 -04:00
parent 46ea32139b
commit 6c4891d591
6 changed files with 89 additions and 109 deletions

View file

@ -1,6 +1,7 @@
#ifndef OPENMC_TALLY_FILTER_MATERIAL_H
#define OPENMC_TALLY_FILTER_MATERIAL_H
#include <cstdint>
#include <sstream>
#include <unordered_map>
#include <vector>

View file

@ -0,0 +1,84 @@
#ifndef OPENMC_TALLY_FILTER_UNIVERSE_H
#define OPENMC_TALLY_FILTER_UNIVERSE_H
#include <cstdint>
#include <sstream>
#include <unordered_map>
#include <vector>
#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<int32_t>(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<int32_t> 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<int32_t> universes_;
std::unordered_map<int32_t, int> map_;
};
} // namespace openmc
#endif // OPENMC_TALLY_FILTER_UNIVERSE_H

View file

@ -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

View file

@ -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)

View file

@ -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;
}

View file

@ -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