Use dynamic_cast for filter type-checking

This commit is contained in:
Sterling Harper 2018-10-25 12:58:09 -04:00
parent 321b255aea
commit 91f4196f0f
11 changed files with 241 additions and 176 deletions

View file

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

View file

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

View file

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

View file

@ -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<int>(filt->cosine_);}

View file

@ -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<LegendreFilter*>(filt_base);
// Check the filter type.
if (!filt) {
set_errmsg("Not a legendre filter.");
return OPENMC_E_INVALID_TYPE;
}
auto l_filt = static_cast<LegendreFilter*>(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<LegendreFilter*>(filt_base);
// Check the filter type.
if (!filt) {
set_errmsg("Not a legendre filter.");
return OPENMC_E_INVALID_TYPE;
}
auto l_filt = static_cast<LegendreFilter*>(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;
}

View file

@ -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<MaterialFilter*>(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<MaterialFilter*>(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<MaterialFilter*>(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<MaterialFilter*>(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;
}

View file

@ -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<MeshFilter*>(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<MeshFilter*>(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<MeshFilter*>(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<MeshFilter*>(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;
}

View file

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

View file

@ -1,5 +1,7 @@
#include "openmc/tallies/filter_sph_harm.h"
#include <utility> // 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<int, SphericalHarmonicsFilter*>
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<SphericalHarmonicsFilter*>(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<SphericalHarmonicsFilter*>(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<SphericalHarmonicsFilter*>(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<SphericalHarmonicsFilter*>(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<SphericalHarmonicsFilter*>(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;

View file

@ -1,5 +1,7 @@
#include "openmc/tallies/filter_sptl_legendre.h"
#include <utility> // 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<int, SpatialLegendreFilter*>
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<SpatialLegendreFilter*>(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<SpatialLegendreFilter*>(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<SpatialLegendreFilter*>(filt);
*axis = static_cast<int>(l_filt->axis_);
*min = l_filt->min_;
*max = l_filt->max_;
// Output the params.
*axis = static_cast<int>(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<SpatialLegendreFilter*>(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<SpatialLegendreFilter*>(filt);
if (axis) l_filt->axis_ = static_cast<LegendreAxis>(*axis);
if (min) l_filt->min_ = *min;
if (max) l_filt->max_ = *max;
// Update the filter.
if (axis) filt->axis_ = static_cast<LegendreAxis>(*axis);
if (min) filt->min_ = *min;
if (max) filt->max_ = *max;
return 0;
}

View file

@ -2,6 +2,7 @@
#include <cmath>
#include <sstream>
#include <utility> // For pair
#include "openmc/capi.h"
#include "openmc/error.h"
@ -119,20 +120,38 @@ ZernikeRadialFilter::set_order(int order)
// C-API functions
//==============================================================================
std::pair<int, ZernikeFilter*>
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<ZernikeFilter*>(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<ZernikeFilter*>(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<ZernikeFilter*>(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<ZernikeFilter*>(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<ZernikeFilter*>(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;
}