Read tally nuclides from XML in C++

This commit is contained in:
Sterling Harper 2019-02-05 16:54:17 -05:00
parent 675ed32b34
commit 22f8749225
3 changed files with 57 additions and 90 deletions

View file

@ -25,6 +25,8 @@ public:
void set_scores(std::vector<std::string> scores);
void set_nuclides(pugi::xml_node node);
//----------------------------------------------------------------------------
// Methods for getting and setting filter/stride data.
@ -41,8 +43,6 @@ public:
//----------------------------------------------------------------------------
// Other methods.
void init_scores(pugi::xml_node node);
void init_triggers(pugi::xml_node node, int i_tally);
//----------------------------------------------------------------------------

View file

@ -447,7 +447,6 @@ contains
integer :: i ! loop over user-specified tallies
integer :: j ! loop over words
integer :: k ! another loop index
integer :: l ! loop over bins
integer :: filter_id ! user-specified identifier for filter
integer :: tally_id ! user-specified identifier for filter
@ -456,20 +455,14 @@ contains
integer :: n ! size of arrays in mesh specification
integer :: n_words ! number of words read
integer :: n_filter ! number of filters
integer :: n_scores ! number of scores
integer :: i_start, i_end
integer(C_INT) :: err
integer :: MT ! user-specified MT for score
logical :: file_exists ! does tallies.xml file exist?
integer, allocatable :: temp_filter(:) ! temporary filter indices
logical :: has_energyout, has_delayedgroup, has_legendre, has_surface, &
has_cell, has_cellfrom, has_meshsurface
logical :: has_energyout
integer :: particle_filter_index
character(MAX_LINE_LEN) :: filename
character(MAX_WORD_LEN) :: word
character(MAX_WORD_LEN) :: score_name
character(MAX_WORD_LEN) :: temp_str
character(MAX_WORD_LEN), allocatable :: sarray(:)
type(TallyFilterContainer), pointer :: f
type(XMLDocument) :: doc
type(XMLNode) :: root
@ -478,11 +471,15 @@ contains
type(XMLNode), allocatable :: node_tal_list(:)
type(XMLNode), allocatable :: node_filt_list(:)
type(TallyDerivative), pointer :: deriv
integer, allocatable :: nuclide_bins(:)
logical :: all_nuclides
interface
subroutine tally_init_scores(tally_ptr, xml_node) bind(C)
subroutine tally_set_scores(tally_ptr, xml_node) bind(C)
import C_PTR
type(C_PTR), value :: tally_ptr
type(C_PTR) :: xml_node
end subroutine
subroutine tally_set_nuclides(tally_ptr, xml_node) bind(C)
import C_PTR
type(C_PTR), value :: tally_ptr
type(C_PTR) :: xml_node
@ -692,25 +689,9 @@ contains
! Check for the presence of certain filter types
has_energyout = (t % energyout_filter() > 0)
has_delayedgroup = (t % delayedgroup_filter() > 0)
has_legendre = .false.
has_cell = .false.
has_cellfrom = .false.
has_surface = .false.
has_meshsurface = .false.
particle_filter_index = 0
do j = 1, t % n_filters()
select type (filt => filters(t % filter(j)) % obj)
type is (LegendreFilter)
has_legendre = .true.
type is (CellFilter)
has_cell = .true.
type is (CellfromFilter)
has_cellfrom = .true.
type is (SurfaceFilter)
has_surface = .true.
type is (MeshSurfaceFilter)
has_meshsurface = .true.
type is (ParticleFilter)
particle_filter_index = j
end select
@ -739,69 +720,12 @@ contains
! =======================================================================
! READ DATA FOR NUCLIDES
all_nuclides = .false.
if (check_for_node(node_tal, "nuclides")) then
! Allocate a temporary string array for nuclides and copy values over
allocate(sarray(node_word_count(node_tal, "nuclides")))
call get_node_array(node_tal, "nuclides", sarray)
if (trim(sarray(1)) == 'all') then
! Handle special case <nuclides>all</nuclides>
allocate(nuclide_bins(n_nuclides + 1))
! Set bins to 1, 2, 3, ..., n_nuclides, -1
nuclide_bins(1:n_nuclides) = (/ (j, j=1, n_nuclides) /)
nuclide_bins(n_nuclides + 1) = -1
! Set flag so we can treat this case specially
all_nuclides = .true.
else
! Any other case, e.g. <nuclides>U-235 Pu-239</nuclides>
n_words = node_word_count(node_tal, "nuclides")
allocate(nuclide_bins(n_words))
do j = 1, n_words
! Check if total material was specified
if (trim(sarray(j)) == 'total') then
nuclide_bins(j) = -1
cycle
end if
! If a specific nuclide was specified
word = sarray(j)
! Search through nuclides
k = nuclide_map_get(to_c_string(word))
if (k == -1) then
call fatal_error("Could not find the nuclide " &
// trim(word) // " specified in tally " &
// trim(to_str(t % id())) // " in any material.")
end if
! Set bin to index in nuclides array
nuclide_bins(j) = k
end do
end if
! Deallocate temporary string array
deallocate(sarray)
else
! No <nuclides> were specified -- create only one bin will be added
! for the total material.
allocate(nuclide_bins(1))
nuclide_bins(1) = -1
end if
! Set the tally nuclides array
call t % set_nuclide_bins(nuclide_bins, all_nuclides)
deallocate(nuclide_bins)
call tally_set_nuclides(t % ptr, node_tal % ptr)
! =======================================================================
! READ DATA FOR SCORES
call tally_init_scores(t % ptr, node_tal % ptr)
call tally_set_scores(t % ptr, node_tal % ptr)
if (check_for_node(node_tal, "scores")) then
n_words = node_word_count(node_tal, "scores")
@ -809,7 +733,7 @@ contains
! Check if tally is compatible with particle type
if (photon_transport) then
if (particle_filter_index == 0) then
do j = 1, n_scores
do j = 1, t % n_score_bins()
select case (t % score_bins(j))
case (SCORE_INVERSE_VELOCITY)
call fatal_error("Particle filter must be used with photon &

View file

@ -529,6 +529,46 @@ Tally::set_scores(std::vector<std::string> scores)
}
}
void
Tally::set_nuclides(pugi::xml_node node)
{
// By default, we tally just the total material rates.
if (!check_for_node(node, "nuclides")) {
nuclides_.push_back(-1);
return;
}
if (get_node_value(node, "nuclides") == "all") {
// This tally should bin every nuclide in the problem. It should also bin
// the total material rates. To achieve this, set the nuclides_ vector to
// 1, 2, 3, ..., -1.
nuclides_.reserve(data::nuclides.size() + 1);
//TODO: off-by-one
for (auto i = 1; i < data::nuclides.size()+1; ++i)
nuclides_.push_back(i);
nuclides_.push_back(-1);
all_nuclides_ = true;
} else {
// The user provided specifics nuclides. Parse it as an array with either
// "total" or a nuclide name like "U-235" in each position.
auto words = get_node_array<std::string>(node, "nuclides");
for (auto word : words) {
if (word == "total") {
nuclides_.push_back(-1);
} else {
auto search = data::nuclide_map.find(word);
if (search == data::nuclide_map.end())
fatal_error("Could not find the nuclide " + word
+ " specified in tally " + std::to_string(id_)
+ " in any material");
//TODO: off-by-one
nuclides_.push_back(search->second + 1);
}
}
}
}
void
Tally::init_triggers(pugi::xml_node node, int i_tally)
{
@ -1329,9 +1369,12 @@ extern "C" {
int tally_get_delayedgroup_filter_c(Tally* tally)
{return tally->delayedgroup_filter_;}
void tally_init_scores(Tally* tally, pugi::xml_node* node)
void tally_set_scores(Tally* tally, pugi::xml_node* node)
{tally->set_scores(*node);}
void tally_set_nuclides(Tally* tally, pugi::xml_node* node)
{tally->set_nuclides(*node);}
void tally_init_triggers(Tally* tally, int i_tally, pugi::xml_node* node)
{tally->init_triggers(*node, i_tally);}