diff --git a/CMakeLists.txt b/CMakeLists.txt index 342dc46361..12d32af5d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -323,7 +323,6 @@ add_library(libopenmc SHARED src/xml_interface.F90 src/tallies/tally.F90 src/tallies/tally_derivative_header.F90 - src/tallies/tally_filter.F90 src/tallies/tally_filter_header.F90 src/tallies/tally_filter_distribcell.F90 src/tallies/tally_filter_particle.F90 diff --git a/include/openmc/capi.h b/include/openmc/capi.h index ef84b78f44..4cad870d3e 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -40,9 +40,8 @@ extern "C" { int openmc_extend_meshes(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end); int openmc_filter_get_id(int32_t index, int32_t* id); - int openmc_filter_get_type(int32_t index, char* type); + int openmc_filter_get_type(int32_t index, const char** type); int openmc_filter_set_id(int32_t index, int32_t id); - int openmc_filter_set_type(int32_t index, const char* type); int openmc_finalize(); int openmc_find_cell(double* xyz, int32_t* index, int32_t* instance); int openmc_get_cell_index(int32_t id, int32_t* index); @@ -82,6 +81,7 @@ extern "C" { int openmc_mesh_set_params(int32_t index, int n, const double* ll, const double* ur, const double* width); int openmc_meshsurface_filter_get_mesh(int32_t index, int32_t* index_mesh); int openmc_meshsurface_filter_set_mesh(int32_t index, int32_t index_mesh); + int openmc_new_filter(const char* type, int32_t* index); int openmc_next_batch(int* status); int openmc_nuclide_name(int index, const char** name); int openmc_plot_geometry(); diff --git a/openmc/capi/filter.py b/openmc/capi/filter.py index 5f6e74bbc8..e75b1a57b6 100644 --- a/openmc/capi/filter.py +++ b/openmc/capi/filter.py @@ -40,15 +40,12 @@ _dll.openmc_extend_filters.errcheck = _error_handler _dll.openmc_filter_get_id.argtypes = [c_int32, POINTER(c_int32)] _dll.openmc_filter_get_id.restype = c_int _dll.openmc_filter_get_id.errcheck = _error_handler -_dll.openmc_filter_get_type.argtypes = [c_int32, c_char_p] +_dll.openmc_filter_get_type.argtypes = [c_int32, POINTER(c_char_p)] _dll.openmc_filter_get_type.restype = c_int _dll.openmc_filter_get_type.errcheck = _error_handler _dll.openmc_filter_set_id.argtypes = [c_int32, c_int32] _dll.openmc_filter_set_id.restype = c_int _dll.openmc_filter_set_id.errcheck = _error_handler -_dll.openmc_filter_set_type.argtypes = [c_int32, c_char_p] -_dll.openmc_filter_set_type.restype = c_int -_dll.openmc_filter_set_type.errcheck = _error_handler _dll.openmc_get_filter_index.argtypes = [c_int32, POINTER(c_int32)] _dll.openmc_get_filter_index.restype = c_int _dll.openmc_get_filter_index.errcheck = _error_handler @@ -77,6 +74,9 @@ _dll.openmc_meshsurface_filter_get_mesh.errcheck = _error_handler _dll.openmc_meshsurface_filter_set_mesh.argtypes = [c_int32, c_int32] _dll.openmc_meshsurface_filter_set_mesh.restype = c_int _dll.openmc_meshsurface_filter_set_mesh.errcheck = _error_handler +_dll.openmc_new_filter.argtypes = [c_char_p, POINTER(c_int32_)] +_dll.openmc_new_filter.restype = c_int +_dll.openmc_new_filter.errcheck = _error_handler _dll.openmc_spatial_legendre_filter_get_order.argtypes = [c_int32, POINTER(c_int)] _dll.openmc_spatial_legendre_filter_get_order.restype = c_int _dll.openmc_spatial_legendre_filter_get_order.errcheck = _error_handler @@ -111,13 +111,10 @@ class Filter(_FortranObjectWithID): raise AllocationError('A filter with ID={} has already ' 'been allocated.'.format(uid)) - # Resize internal array - index = c_int32() - _dll.openmc_extend_filters(1, index, None) - # Set the filter type -- note that the filter_type attribute # only exists on subclasses! - _dll.openmc_filter_set_type(index, cls.filter_type.encode()) + index = c_int32() + _dll.openmc_new_filter(cls.filter_type.encode(), index) index = index.value else: index = mapping[uid]._index diff --git a/src/tallies/filter.cpp b/src/tallies/filter.cpp index 66a26a5bc8..58593c2295 100644 --- a/src/tallies/filter.cpp +++ b/src/tallies/filter.cpp @@ -44,6 +44,10 @@ namespace model { std::unordered_map filter_map; } +//============================================================================== +// Non-member functions +//============================================================================== + Filter* allocate_filter(const std::string& type) { @@ -97,6 +101,28 @@ allocate_filter(const std::string& type) return model::tally_filters.back().get(); } +//============================================================================== +// C API functions +//============================================================================== + +extern "C" int +openmc_filter_get_type(int32_t index, const char** type) +{ + int err = verify_filter(index); + if (err) return err; + + // TODO: off-by-one + *type = model::tally_filters[index-1]->type().c_str(); +} + +extern "C" int +openmc_new_filter(const char* type, int32_t* index) +{ + allocate_filter(type); + // TODO: off-by-one + *index = model::tally_filters.size(); + return 0; +} //============================================================================== // Fortran compatibility functions diff --git a/src/tallies/tally_filter.F90 b/src/tallies/tally_filter.F90 deleted file mode 100644 index 9a8eff9d52..0000000000 --- a/src/tallies/tally_filter.F90 +++ /dev/null @@ -1,172 +0,0 @@ -module tally_filter - - use, intrinsic :: ISO_C_BINDING - - use error - use string, only: to_f_string - use tally_filter_header - - ! Inherit other filters - use tally_filter_distribcell - use tally_filter_particle - use tally_filter_sph_harm - - implicit none - -contains - -!=============================================================================== -! C API FUNCTIONS -!=============================================================================== - - function openmc_filter_get_type(index, type) result(err) bind(C) - ! Get the type of a filter - integer(C_INT32_T), value, intent(in) :: index - character(kind=C_CHAR), intent(out) :: type(*) - integer(C_INT) :: err - - integer :: i - character(20) :: type_ - - err = verify_filter(index) - if (err == 0) then - ! Get type as a Fortran string - select type (f => filters(index) % obj) - type is (AzimuthalFilter) - type_ = 'azimuthal' - type is (CellFilter) - type_ = 'cell' - type is (CellbornFilter) - type_ = 'cellborn' - type is (CellfromFilter) - type_ = 'cellfrom' - type is (DelayedGroupFilter) - type_ = 'delayedgroup' - type is (DistribcellFilter) - type_ = 'distribcell' - type is (EnergyFilter) - type_ = 'energy' - type is (EnergyoutFilter) - type_ = 'energyout' - type is (EnergyFunctionFilter) - type_ = 'energyfunction' - type is (LegendreFilter) - type_ = 'legendre' - type is (MaterialFilter) - type_ = 'material' - type is (MeshFilter) - type_ = 'mesh' - type is (MeshSurfaceFilter) - type_ = 'meshsurface' - type is (MuFilter) - type_ = 'mu' - type is (PolarFilter) - type_ = 'polar' - type is (SphericalHarmonicsFilter) - type_ = 'sphericalharmonics' - type is (SpatialLegendreFilter) - type_ = 'spatiallegendre' - type is (SurfaceFilter) - type_ = 'surface' - type is (UniverseFilter) - type_ = 'universe' - type is (ZernikeFilter) - type_ = 'zernike' - type is (ParticleFilter) - type_ = 'particle' - type is (ZernikeRadialFilter) - type_ = 'zernikeradial' - end select - - ! Convert Fortran string to null-terminated C string. We assume the - ! caller has allocated a char array buffer - do i = 1, len_trim(type_) - type(i) = type_(i:i) - end do - type(len_trim(type_) + 1) = C_NULL_CHAR - end if - - end function openmc_filter_get_type - - - function openmc_filter_set_type(index, type) result(err) bind(C) - ! Set the type of a filter - integer(C_INT32_T), value, intent(in) :: index - character(kind=C_CHAR), intent(in) :: type(*) - integer(C_INT) :: err - - character(:), allocatable :: type_ - - ! Convert C string to Fortran string - type_ = to_f_string(type) - - err = 0 - if (index >= 1 .and. index <= n_filters) then - if (allocated(filters(index) % obj)) then - err = E_ALLOCATE - call set_errmsg("Filter type has already been set.") - else - select case (type_) - case ('azimuthal') - allocate(AzimuthalFilter :: filters(index) % obj) - case ('cell') - allocate(CellFilter :: filters(index) % obj) - case ('cellborn') - allocate(CellbornFilter :: filters(index) % obj) - case ('cellfrom') - allocate(CellFromFilter :: filters(index) % obj) - case ('delayedgroup') - allocate(DelayedGroupFilter :: filters(index) % obj) - case ('distribcell') - allocate(DistribcellFilter :: filters(index) % obj) - case ('energy') - allocate(EnergyFilter :: filters(index) % obj) - case ('energyout') - allocate(EnergyoutFilter :: filters(index) % obj) - case ('energyfunction') - allocate(EnergyFunctionFilter :: filters(index) % obj) - case ('legendre') - allocate(LegendreFilter :: filters(index) % obj) - case ('material') - allocate(MaterialFilter :: filters(index) % obj) - case ('mesh') - allocate(MeshFilter :: filters(index) % obj) - case ('meshsurface') - allocate(MeshSurfaceFilter :: filters(index) % obj) - case ('mu') - allocate(MuFilter :: filters(index) % obj) - case ('particle') - allocate(ParticleFilter :: filters(index) % obj) - case ('polar') - allocate(PolarFilter :: filters(index) % obj) - case ('sphericalharmonics') - allocate(SphericalHarmonicsFilter :: filters(index) % obj) - case ('spatiallegendre') - allocate(SpatialLegendreFilter :: filters(index) % obj) - case ('surface') - allocate(SurfaceFilter :: filters(index) % obj) - case ('universe') - allocate(UniverseFilter :: filters(index) % obj) - case ('zernike') - allocate(ZernikeFilter :: filters(index) % obj) - case ('zernikeradial') - allocate(ZernikeRadialFilter :: filters(index) % obj) - case default - err = E_UNASSIGNED - call set_errmsg("Unknown filter type: " // trim(type_)) - end select - - !filters(index) % obj % ptr = allocate_filter(type) - if (.not. c_associated(filters(index) % obj % ptr)) then - err = E_UNASSIGNED - call set_errmsg("Could not allocate C++ tally filter") - end if - - end if - else - err = E_OUT_OF_BOUNDS - call set_errmsg("Index in filters array is out of bounds.") - end if - end function openmc_filter_set_type - -end module tally_filter