Add framework for calling C++ filters from F90

This commit is contained in:
Sterling Harper 2018-09-19 10:52:07 -04:00
parent 0c8ea4f31f
commit 1cc0271f4c
7 changed files with 157 additions and 3 deletions

View file

@ -4,6 +4,8 @@
#include <cstdint>
#include <vector>
#include "openmc/xml_interface.h"
namespace openmc {
@ -17,8 +19,11 @@ class TallyFilterMatch;
extern std::vector<TallyFilterMatch> filter_matches;
#pragma omp threadprivate(filter_matches)
class TallyFilter;
extern std::vector<TallyFilter*> tally_filters;
//==============================================================================
//! Stores bins and weights for filtered tally events
//! Stores bins and weights for filtered tally events.
//==============================================================================
class TallyFilterMatch
@ -30,5 +35,16 @@ public:
bool bins_present;
};
//==============================================================================
//! Modifies tally score events.
//==============================================================================
class TallyFilter
{
public:
virtual void from_xml(pugi::xml_node node) = 0;
virtual void initialize() = 0;
};
} // namespace openmc
#endif // OPENMC_TALLY_FILTER
#endif // OPENMC_TALLY_FILTER_H

View file

@ -0,0 +1,46 @@
#ifndef OPENMC_TALLY_FILTER_CELL_H
#define OPENMC_TALLY_FILTER_CELL_H
#include <cstdint>
#include <sstream>
#include <vector>
#include "openmc/cell.h"
#include "openmc/error.h"
#include "openmc/tallies/tally_filter.h"
namespace openmc {
class CellFilter : public TallyFilter
{
public:
virtual void
from_xml(pugi::xml_node node)
{
cells_ = get_node_array<int32_t>(node, "bins");
}
virtual void
initialize()
{
for (auto& c : cells_) {
auto search = cell_map.find(c);
if (search != cell_map.end()) {
c = search->second;
} else {
std::stringstream err_msg;
err_msg << "Could not find cell " << c << " specified on tally filter.";
fatal_error(err_msg);
}
}
//TODO: mapping
}
protected:
std::vector<int32_t> cells_;
};
} // namespace openmc
#endif // OPENMC_TALLY_FILTER_CELL_H

View file

@ -604,6 +604,20 @@ read_cells(pugi::xml_node* node)
cells.push_back(new Cell(cell_node));
}
// Fill the cell map.
// TODO: update this map when openmc_extend_cells is called
for (int i = 0; i < cells.size(); i++) {
int32_t id = cells[i]->id_;
auto search = cell_map.find(id);
if (search == cell_map.end()) {
cell_map[id] = i;
} else {
std::stringstream err_msg;
err_msg << "Two or more cells use the same unique ID: " << id;
fatal_error(err_msg);
}
}
// Populate the Universe vector and map.
for (int i = 0; i < cells.size(); i++) {
int32_t uid = cells[i]->universe_;

View file

@ -114,6 +114,14 @@ contains
character(:), allocatable :: type_
interface
function allocate_filter(type) result(ptr) bind(C)
import C_CHAR, C_PTR
character(kind=C_CHAR), intent(in) :: type(*)
type(C_PTR) :: ptr
end function allocate_filter
end interface
! Convert C string to Fortran string
type_ = to_f_string(type)
@ -128,6 +136,14 @@ contains
allocate(AzimuthalFilter :: filters(index) % obj)
case ('cell')
allocate(CellFilter :: filters(index) % obj)
select type(filt => filters(index) % obj)
type is (CellFilter)
filt % ptr = allocate_filter(type)
if (.not. c_associated(filt % ptr)) then
err = E_UNASSIGNED
call set_errmsg("Could not allocate C++ tally filter")
end if
end select
case ('cellborn')
allocate(CellbornFilter :: filters(index) % obj)
case ('cellfrom')

View file

@ -1,5 +1,9 @@
#include "openmc/tallies/tally_filter.h"
#include <string>
#include "openmc/tallies/tally_filter_cell.h"
namespace openmc {
@ -8,6 +12,7 @@ namespace openmc {
//==============================================================================
std::vector<TallyFilterMatch> filter_matches;
std::vector<TallyFilter*> tally_filters;
//==============================================================================
// Fortran compatibility functions
@ -48,6 +53,23 @@ extern "C" {
void
filter_match_bins_set_data(TallyFilterMatch* match, int indx, int val)
{match->bins.at(indx-1) = val;}
TallyFilter*
allocate_filter(const char* type)
{
std::string type_ {type};
if (type_ == "cell") {
tally_filters.push_back(new CellFilter());
return tally_filters.back();
} else {
return nullptr;
}
}
void filter_from_xml(TallyFilter* filt, pugi::xml_node* node)
{filt->from_xml(*node);}
void filter_initialize(TallyFilter* filt) {filt->initialize();}
}
} // namespace openmc

View file

@ -20,7 +20,7 @@ module tally_filter_cell
! CELLFILTER specifies which geometric cells tally events reside in.
!===============================================================================
type, public, extends(TallyFilter) :: CellFilter
type, public, extends(CppTallyFilter) :: CellFilter
integer(C_INT32_T), allocatable :: cells(:)
type(DictIntInt) :: map
contains
@ -39,6 +39,8 @@ contains
integer :: n
call this % from_xml_c(node)
! Determine how many bins were given
n = node_word_count(node, "bins")
@ -91,6 +93,8 @@ contains
integer :: i, id
integer :: val
call this % initialize_c()
! Convert ids to indices.
do i = 1, this % n_bins
id = this % cells(i)

View file

@ -124,6 +124,16 @@ module tally_filter_header
end interface
!===============================================================================
!===============================================================================
type, public, abstract, extends(TallyFilter) :: CppTallyFilter
type(C_PTR) :: ptr
contains
procedure :: from_xml_c
procedure :: initialize_c
end type CppTallyFilter
!===============================================================================
! TALLYFILTERCONTAINER contains an allocatable TallyFilter object for arrays of
! TallyFilters
@ -265,6 +275,32 @@ contains
class(TallyFilter), intent(inout) :: this
end subroutine filter_initialize
!===============================================================================
subroutine from_xml_c(this, node)
class(CppTallyFilter), intent(inout) :: this
class(XMLNode), intent(in) :: node
interface
subroutine filter_from_xml(filt, node) bind(C)
import C_PTR
type(C_PTR), value :: filt
type(C_PTR) :: node
end subroutine filter_from_xml
end interface
call filter_from_xml(this % ptr, node % ptr)
end subroutine from_xml_c
subroutine initialize_c(this)
class(CppTallyFilter), intent(inout) :: this
interface
subroutine filter_initialize(filt) bind(C)
import C_PTR
type(C_PTR), value :: filt
end subroutine filter_initialize
end interface
call filter_initialize(this % ptr)
end subroutine initialize_c
!===============================================================================
! FREE_MEMORY_TALLY_FILTER deallocates global arrays defined in this module
!===============================================================================