From 91f4196f0f444f4a68106948bd54f33729f8b71c Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Thu, 25 Oct 2018 12:58:09 -0400 Subject: [PATCH] Use dynamic_cast for filter type-checking --- include/openmc/tallies/filter.h | 4 +- include/openmc/tallies/filter_mesh.h | 5 ++ include/openmc/tallies/filter_meshsurface.h | 4 +- src/tallies/filter.cpp | 2 +- src/tallies/filter_legendre.cpp | 32 ++++--- src/tallies/filter_material.cpp | 38 +++++---- src/tallies/filter_mesh.cpp | 46 ++++++---- src/tallies/filter_meshsurface.cpp | 16 ++-- src/tallies/filter_sph_harm.cpp | 87 ++++++++++--------- src/tallies/filter_sptl_legendre.cpp | 93 ++++++++++++--------- src/tallies/filter_zernike.cpp | 90 +++++++++++--------- 11 files changed, 241 insertions(+), 176 deletions(-) diff --git a/include/openmc/tallies/filter.h b/include/openmc/tallies/filter.h index 286497d37..7920191aa 100644 --- a/include/openmc/tallies/filter.h +++ b/include/openmc/tallies/filter.h @@ -43,7 +43,7 @@ public: class Filter { public: - virtual ~Filter() = 0; + virtual ~Filter() = default; virtual std::string type() const = 0; @@ -76,8 +76,6 @@ public: int n_bins_; }; -inline Filter::~Filter() {} - //============================================================================== extern "C" void free_memory_tally_c(); diff --git a/include/openmc/tallies/filter_mesh.h b/include/openmc/tallies/filter_mesh.h index 250eb00e0..a6caa8f56 100644 --- a/include/openmc/tallies/filter_mesh.h +++ b/include/openmc/tallies/filter_mesh.h @@ -29,6 +29,11 @@ public: std::string text_label(int bin) const override; + virtual int32_t mesh() const {return mesh_;} + + virtual void set_mesh(int32_t mesh); + +protected: int32_t mesh_; }; diff --git a/include/openmc/tallies/filter_meshsurface.h b/include/openmc/tallies/filter_meshsurface.h index 08218ac3d..32393cfac 100644 --- a/include/openmc/tallies/filter_meshsurface.h +++ b/include/openmc/tallies/filter_meshsurface.h @@ -10,12 +10,12 @@ class MeshSurfaceFilter : public MeshFilter public: std::string type() const override {return "meshsurface";} - void from_xml(pugi::xml_node node) override; - void get_all_bins(const Particle* p, int estimator, FilterMatch& match) const override; std::string text_label(int bin) const override; + + void set_mesh(int32_t mesh) override; }; } // namespace openmc diff --git a/src/tallies/filter.cpp b/src/tallies/filter.cpp index 3d7b35726..44758f379 100644 --- a/src/tallies/filter.cpp +++ b/src/tallies/filter.cpp @@ -161,7 +161,7 @@ extern "C" { int filter_n_bins(Filter* filt) {return filt->n_bins_;} - int mesh_filter_get_mesh(MeshFilter* filt) {return filt->mesh_;} + int mesh_filter_get_mesh(MeshFilter* filt) {return filt->mesh();} int sphharm_filter_get_cosine(SphericalHarmonicsFilter* filt) {return static_cast(filt->cosine_);} diff --git a/src/tallies/filter_legendre.cpp b/src/tallies/filter_legendre.cpp index 32cedcfa0..3b59fa763 100644 --- a/src/tallies/filter_legendre.cpp +++ b/src/tallies/filter_legendre.cpp @@ -47,35 +47,45 @@ LegendreFilter::text_label(int bin) const extern "C" int openmc_legendre_filter_get_order(int32_t index, int* order) { + // Make sure this is a valid index to an allocated filter. int err = verify_filter(index); if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "legendre") { - set_errmsg("Tried to get order on a non-expansion filter."); + // Get a pointer to the filter and downcast. + auto* filt_base = filter_from_f(index); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { + set_errmsg("Not a legendre filter."); return OPENMC_E_INVALID_TYPE; } - auto l_filt = static_cast(filt); - *order = l_filt->order_; + // Output the order. + *order = filt->order_; return 0; } extern "C" int openmc_legendre_filter_set_order(int32_t index, int order) { + // Make sure this is a valid index to an allocated filter. int err = verify_filter(index); if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "legendre") { - set_errmsg("Tried to set order on a non-expansion filter."); + // Get a pointer to the filter and downcast. + auto* filt_base = filter_from_f(index); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { + set_errmsg("Not a legendre filter."); return OPENMC_E_INVALID_TYPE; } - auto l_filt = static_cast(filt); - l_filt->order_ = order; - l_filt->n_bins_ = order + 1; + // Update the filter. + filt->order_ = order; + filt->n_bins_ = order + 1; filter_update_n_bins(index); return 0; } diff --git a/src/tallies/filter_material.cpp b/src/tallies/filter_material.cpp index 2b6542d78..0334efae9 100644 --- a/src/tallies/filter_material.cpp +++ b/src/tallies/filter_material.cpp @@ -72,40 +72,50 @@ MaterialFilter::text_label(int bin) const extern "C" int openmc_material_filter_get_bins(int32_t index, int32_t** bins, int32_t* n) { + // Make sure this is a valid index to an allocated filter. int err = verify_filter(index); if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "material") { + // Get a pointer to the filter and downcast. + auto* filt_base = filter_from_f(index); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { set_errmsg("Tried to get material filter bins on a non-material filter."); return OPENMC_E_INVALID_TYPE; } - auto mat_filt = static_cast(filt); - *bins = mat_filt->materials_.data(); - *n = mat_filt->materials_.size(); + // Output the bins. + *bins = filt->materials_.data(); + *n = filt->materials_.size(); return 0; } extern "C" int openmc_material_filter_set_bins(int32_t index, int32_t n, const int32_t* bins) { + // Make sure this is a valid index to an allocated filter. int err = verify_filter(index); if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "material") { + // Get a pointer to the filter and downcast. + auto* filt_base = filter_from_f(index); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { set_errmsg("Tried to set material filter bins on a non-material filter."); return OPENMC_E_INVALID_TYPE; } - auto mat_filt = static_cast(filt); - mat_filt->materials_.clear(); - mat_filt->materials_.resize(n); - for (int i = 0; i < n; i++) mat_filt->materials_[i] = bins[i]; - mat_filt->n_bins_ = mat_filt->materials_.size(); - mat_filt->map_.clear(); - for (int i = 0; i < n; i++) mat_filt->map_[mat_filt->materials_[i]] = i; + // Update the filter. + filt->materials_.clear(); + filt->materials_.resize(n); + for (int i = 0; i < n; i++) filt->materials_[i] = bins[i]; + filt->n_bins_ = filt->materials_.size(); + filt->map_.clear(); + for (int i = 0; i < n; i++) filt->map_[filt->materials_[i]] = i; filter_update_n_bins(index); return 0; } diff --git a/src/tallies/filter_mesh.cpp b/src/tallies/filter_mesh.cpp index 41b8e642b..5ff54bcf5 100644 --- a/src/tallies/filter_mesh.cpp +++ b/src/tallies/filter_mesh.cpp @@ -22,15 +22,12 @@ MeshFilter::from_xml(pugi::xml_node node) auto id = bins_[0]; auto search = mesh_map.find(id); if (search != mesh_map.end()) { - mesh_ = search->second; + set_mesh(search->second); } else{ std::stringstream err_msg; err_msg << "Could not find cell " << id << " specified on tally filter."; fatal_error(err_msg); } - - n_bins_ = 1; - for (auto dim : meshes[mesh_]->shape_) n_bins_ *= dim; } void @@ -74,6 +71,14 @@ MeshFilter::text_label(int bin) const return out.str(); } +void +MeshFilter::set_mesh(int32_t mesh) +{ + mesh_ = mesh; + n_bins_ = 1; + for (auto dim : meshes[mesh_]->shape_) n_bins_ *= dim; +} + //============================================================================== // C-API functions //============================================================================== @@ -81,45 +86,50 @@ MeshFilter::text_label(int bin) const extern "C" int openmc_mesh_filter_get_mesh(int32_t index, int32_t* index_mesh) { + // Make sure this is a valid index to an allocated filter. int err = verify_filter(index); if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "mesh" && filt->type() != "meshsurface") { + // Get a pointer to the filter and downcast. + auto* filt_base = filter_from_f(index); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { set_errmsg("Tried to get mesh on a non-mesh filter."); return OPENMC_E_INVALID_TYPE; } - auto mesh_filt = static_cast(filt); - *index_mesh = mesh_filt->mesh_; + // Output the mesh. + *index_mesh = filt->mesh(); return 0; } extern "C" int openmc_mesh_filter_set_mesh(int32_t index, int32_t index_mesh) { + // Make sure this is a valid index to an allocated filter. int err = verify_filter(index); if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "mesh" && filt->type() != "meshsurface") { + // Get a pointer to the filter and downcast. + auto* filt_base = filter_from_f(index); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { set_errmsg("Tried to set mesh on a non-mesh filter."); return OPENMC_E_INVALID_TYPE; } + // Check the mesh index. if (index_mesh < 0 || index_mesh >= meshes.size()) { set_errmsg("Index in 'meshes' array is out of bounds."); return OPENMC_E_OUT_OF_BOUNDS; } - auto mesh_filt = static_cast(filt); - mesh_filt->mesh_ = index_mesh; - if (filt->type() == "mesh") { - mesh_filt->n_bins_ = 1; - } else { - filt->n_bins_ = 4 * meshes[index_mesh]->n_dimension_; - } - for (auto dim : meshes[index_mesh]->shape_) mesh_filt->n_bins_ *= dim; + // Update the filter. + filt->set_mesh(index_mesh); filter_update_n_bins(index); return 0; } diff --git a/src/tallies/filter_meshsurface.cpp b/src/tallies/filter_meshsurface.cpp index aafa91e6e..8074b4a4c 100644 --- a/src/tallies/filter_meshsurface.cpp +++ b/src/tallies/filter_meshsurface.cpp @@ -7,14 +7,6 @@ namespace openmc { -void -MeshSurfaceFilter::from_xml(pugi::xml_node node) -{ - MeshFilter::from_xml(node); - n_bins_ = 4 * meshes[mesh_]->n_dimension_;; - for (auto dim : meshes[mesh_]->shape_) n_bins_ *= dim; -} - void MeshSurfaceFilter::get_all_bins(const Particle* p, int estimator, FilterMatch& match) const @@ -79,6 +71,14 @@ MeshSurfaceFilter::text_label(int bin) const return out; } +void +MeshSurfaceFilter::set_mesh(int32_t mesh) +{ + mesh_ = mesh; + n_bins_ = 4 * meshes[mesh_]->n_dimension_; + for (auto dim : meshes[mesh_]->shape_) n_bins_ *= dim; +} + //============================================================================== // C-API functions //============================================================================== diff --git a/src/tallies/filter_sph_harm.cpp b/src/tallies/filter_sph_harm.cpp index 1c085bcce..764c56223 100644 --- a/src/tallies/filter_sph_harm.cpp +++ b/src/tallies/filter_sph_harm.cpp @@ -1,5 +1,7 @@ #include "openmc/tallies/filter_sph_harm.h" +#include // For pair + #include "openmc/capi.h" #include "openmc/error.h" #include "openmc/math_functions.h" @@ -87,37 +89,52 @@ SphericalHarmonicsFilter::text_label(int bin) const // C-API functions //============================================================================== +std::pair +check_sphharm_filter(int32_t index) +{ + // Make sure this is a valid index to an allocated filter. + int err = verify_filter(index); + if (err) { + return {err, nullptr}; + } + + // Get a pointer to the filter and downcast. + auto* filt_base = filter_from_f(index); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { + set_errmsg("Not a spherical harmonics filter."); + err = OPENMC_E_INVALID_TYPE; + } + return {err, filt}; +} + extern "C" int openmc_sphharm_filter_get_order(int32_t index, int* order) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_sphharm_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "sphericalharmonics") { - set_errmsg("Not a spherical harmonics filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto sph_filt = static_cast(filt); - *order = sph_filt->order_; + // Output the order. + *order = filt->order_; return 0; } extern "C" int openmc_sphharm_filter_get_cosine(int32_t index, char cosine[]) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_sphharm_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "sphericalharmonics") { - set_errmsg("Not a spherical harmonics filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto sph_filt = static_cast(filt); - if (sph_filt->cosine_ == SphericalHarmonicsCosine::scatter) { + // Output the cosine. + if (filt->cosine_ == SphericalHarmonicsCosine::scatter) { strcpy(cosine, "scatter"); } else { strcpy(cosine, "particle"); @@ -128,18 +145,15 @@ openmc_sphharm_filter_get_cosine(int32_t index, char cosine[]) extern "C" int openmc_sphharm_filter_set_order(int32_t index, int order) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_sphharm_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "sphericalharmonics") { - set_errmsg("Not a spherical harmonics filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto sph_filt = static_cast(filt); - sph_filt->order_ = order; - sph_filt->n_bins_ = (order + 1) * (order + 1); + // Update the filter. + filt->order_ = order; + filt->n_bins_ = (order + 1) * (order + 1); filter_update_n_bins(index); return 0; } @@ -147,20 +161,17 @@ openmc_sphharm_filter_set_order(int32_t index, int order) extern "C" int openmc_sphharm_filter_set_cosine(int32_t index, const char cosine[]) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_sphharm_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "sphericalharmonics") { - set_errmsg("Not a spherical harmonics filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto sph_filt = static_cast(filt); + // Update the filter. if (strcmp(cosine, "scatter") == 0) { - sph_filt->cosine_ = SphericalHarmonicsCosine::scatter; + filt->cosine_ = SphericalHarmonicsCosine::scatter; } else if (strcmp(cosine, "particle") == 0) { - sph_filt->cosine_ = SphericalHarmonicsCosine::particle; + filt->cosine_ = SphericalHarmonicsCosine::particle; } else { set_errmsg("Invalid spherical harmonics cosine."); return OPENMC_E_INVALID_ARGUMENT; diff --git a/src/tallies/filter_sptl_legendre.cpp b/src/tallies/filter_sptl_legendre.cpp index 4043a4389..3f93be1cb 100644 --- a/src/tallies/filter_sptl_legendre.cpp +++ b/src/tallies/filter_sptl_legendre.cpp @@ -1,5 +1,7 @@ #include "openmc/tallies/filter_sptl_legendre.h" +#include // For pair + #include "openmc/capi.h" #include "openmc/error.h" #include "openmc/math_functions.h" @@ -94,20 +96,38 @@ SpatialLegendreFilter::text_label(int bin) const // C-API functions //============================================================================== +std::pair +check_sptl_legendre_filter(int32_t index) +{ + // Make sure this is a valid index to an allocated filter. + int err = verify_filter(index); + if (err) { + return {err, nullptr}; + } + + // Get a pointer to the filter and downcast. + auto* filt_base = filter_from_f(index); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { + set_errmsg("Not a spatial Legendre filter."); + err = OPENMC_E_INVALID_TYPE; + } + return {err, filt}; +} + extern "C" int openmc_spatial_legendre_filter_get_order(int32_t index, int* order) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_sptl_legendre_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "spatiallegendre") { - set_errmsg("Not a spatial Legendre filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto l_filt = static_cast(filt); - *order = l_filt->order_; + // Output the order. + *order = filt->order_; return 0; } @@ -115,37 +135,31 @@ extern "C" int openmc_spatial_legendre_filter_get_params(int32_t index, int* axis, double* min, double* max) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_sptl_legendre_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "spatiallegendre") { - set_errmsg("Not a spatial Legendre filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto l_filt = static_cast(filt); - *axis = static_cast(l_filt->axis_); - *min = l_filt->min_; - *max = l_filt->max_; + // Output the params. + *axis = static_cast(filt->axis_); + *min = filt->min_; + *max = filt->max_; return 0; } extern "C" int openmc_spatial_legendre_filter_set_order(int32_t index, int order) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_sptl_legendre_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "spatiallegendre") { - set_errmsg("Not a spatial Legendre filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto l_filt = static_cast(filt); - l_filt->order_ = order; - l_filt->n_bins_ = order + 1; + // Update the filter. + filt->order_ = order; + filt->n_bins_ = order + 1; filter_update_n_bins(index); return 0; } @@ -154,19 +168,16 @@ extern "C" int openmc_spatial_legendre_filter_set_params(int32_t index, const int* axis, const double* min, const double* max) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_sptl_legendre_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "spatiallegendre") { - set_errmsg("Not a spatial Legendre filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto l_filt = static_cast(filt); - if (axis) l_filt->axis_ = static_cast(*axis); - if (min) l_filt->min_ = *min; - if (max) l_filt->max_ = *max; + // Update the filter. + if (axis) filt->axis_ = static_cast(*axis); + if (min) filt->min_ = *min; + if (max) filt->max_ = *max; return 0; } diff --git a/src/tallies/filter_zernike.cpp b/src/tallies/filter_zernike.cpp index ed658e2d2..198bd8cb7 100644 --- a/src/tallies/filter_zernike.cpp +++ b/src/tallies/filter_zernike.cpp @@ -2,6 +2,7 @@ #include #include +#include // For pair #include "openmc/capi.h" #include "openmc/error.h" @@ -119,20 +120,38 @@ ZernikeRadialFilter::set_order(int order) // C-API functions //============================================================================== +std::pair +check_zernike_filter(int32_t index) +{ + // Make sure this is a valid index to an allocated filter. + int err = verify_filter(index); + if (err) { + return {err, nullptr}; + } + + // Get a pointer to the filter and downcast. + auto* filt_base = filter_from_f(index); + auto* filt = dynamic_cast(filt_base); + + // Check the filter type. + if (!filt) { + set_errmsg("Not a Zernike filter."); + err = OPENMC_E_INVALID_TYPE; + } + return {err, filt}; +} + extern "C" int openmc_zernike_filter_get_order(int32_t index, int* order) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_zernike_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "zernike" && filt->type() != "zernikeradial") { - set_errmsg("Not a Zernike filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto z_filt = static_cast(filt); - *order = z_filt->order(); + // Output the order. + *order = filt->order(); return 0; } @@ -140,36 +159,30 @@ extern "C" int openmc_zernike_filter_get_params(int32_t index, double* x, double* y, double* r) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_zernike_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "zernike" && filt->type() != "zernikeradial") { - set_errmsg("Not a Zernike filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto z_filt = static_cast(filt); - *x = z_filt->x_; - *y = z_filt->y_; - *r = z_filt->r_; + // Output the params. + *x = filt->x_; + *y = filt->y_; + *r = filt->r_; return 0; } extern "C" int openmc_zernike_filter_set_order(int32_t index, int order) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_zernike_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "zernike" && filt->type() != "zernikeradial") { - set_errmsg("Not a Zernike filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto z_filt = static_cast(filt); - z_filt->set_order(order); + // Update the filter. + filt->set_order(order); filter_update_n_bins(index); return 0; } @@ -178,19 +191,16 @@ extern "C" int openmc_zernike_filter_set_params(int32_t index, const double* x, const double* y, const double* r) { - int err = verify_filter(index); + // Check the filter. + auto check_result = check_zernike_filter(index); + auto err = check_result.first; + auto filt = check_result.second; if (err) return err; - auto filt = filter_from_f(index); - if (filt->type() != "zernike" && filt->type() != "zernikeradial") { - set_errmsg("Not a Zernike filter."); - return OPENMC_E_INVALID_TYPE; - } - - auto z_filt = static_cast(filt); - if (x) z_filt->x_ = *x; - if (y) z_filt->y_ = *y; - if (r) z_filt->r_ = *r; + // Update the filter. + if (x) filt->x_ = *x; + if (y) filt->y_ = *y; + if (r) filt->r_ = *r; return 0; }