Move mesh C API functions to C++

This commit is contained in:
Paul Romano 2018-08-29 14:33:05 -05:00
parent fe76ad695f
commit fb22413e8d
6 changed files with 213 additions and 216 deletions

View file

@ -71,7 +71,7 @@ extern "C" {
int openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n);
int openmc_mesh_set_id(int32_t index, int32_t id);
int openmc_mesh_set_dimension(int32_t index, int n, const int* dims);
int openmc_mesh_set_params(int32_t index, const double* ll, const double* ur, const double* width, int n);
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_next_batch(int* status);

View file

@ -1,7 +1,6 @@
#ifndef OPENMC_MESH_H
#define OPENMC_MESH_H
#include <cstdint> // for size_t
#include <memory> // for unique_ptr
#include <vector>
#include <unordered_map>
@ -22,6 +21,7 @@ namespace openmc {
class RegularMesh {
public:
// Constructors
RegularMesh() = default;
RegularMesh(pugi::xml_node node);
// Methods

View file

@ -11,7 +11,7 @@ module openmc_api
use hdf5_interface
use material_header
use math
use mesh_header
use mesh_header, only: free_memory_mesh
use message_passing
use nuclide_header
use initialize, only: openmc_init_f

View file

@ -1,5 +1,6 @@
#include "openmc/mesh.h"
#include <cstddef> // for size_t
#include <cmath> // for ceil
#include <string>
@ -8,6 +9,7 @@
#include "xtensor/xsort.hpp"
#include "xtensor/xtensor.hpp"
#include "openmc/capi.h"
#include "openmc/constants.h"
#include "openmc/error.h"
#include "openmc/hdf5_interface.h"
@ -519,4 +521,143 @@ void RegularMesh::to_hdf5(hid_t group)
close_group(mesh_group);
}
//==============================================================================
// C API functions
//==============================================================================
//! Extend the meshes array by n elements
extern "C" int
openmc_extend_meshes(int32_t n, int32_t* index_start, int32_t* index_end)
{
if (!index_start) *index_start = meshes.size();
for (int i = 0; i < n; ++i) {
meshes.emplace_back(new RegularMesh{});
}
if (!index_end) *index_end = meshes.size() - 1;
return 0;
}
//! Return the index in the meshes array of a mesh with a given ID
extern "C" int
openmc_get_mesh_index(int32_t id, int32_t* index)
{
auto pair = mesh_map.find(id);
if (pair == mesh_map.end()) {
set_errmsg("No mesh exists with ID=" + std::to_string(id) + ".");
return OPENMC_E_INVALID_ID;
}
*index = pair->second;
return 0;
}
// Return the ID of a mesh
extern "C" int
openmc_mesh_get_id(int32_t index, int32_t* id)
{
if (index < 0 || index >= meshes.size()) {
set_errmsg("Index in meshes array is out of bounds.");
return OPENMC_E_OUT_OF_BOUNDS;
}
*id = meshes[index]->id_;
return 0;
}
//! Set the ID of a mesh
extern "C" int
openmc_mesh_set_id(int32_t index, int32_t id)
{
if (index < 0 || index >= meshes.size()) {
set_errmsg("Index in meshes array is out of bounds.");
return OPENMC_E_OUT_OF_BOUNDS;
}
meshes[index]->id_ = id;
mesh_map[id] = index;
return 0;
}
//! Get the dimension of a mesh
extern "C" int
openmc_mesh_get_dimension(int32_t index, int** dims, int* n)
{
if (index < 0 || index >= meshes.size()) {
set_errmsg("Index in meshes array is out of bounds.");
return OPENMC_E_OUT_OF_BOUNDS;
}
*dims = meshes[index]->shape_.data();
*n = meshes[index]->n_dimension_;
return 0;
}
//! Set the dimension of a mesh
extern "C" int
openmc_mesh_set_dimension(int32_t index, int n, const int* dims)
{
if (index < 0 || index >= meshes.size()) {
set_errmsg("Index in meshes array is out of bounds.");
return OPENMC_E_OUT_OF_BOUNDS;
}
// Copy dimension
std::vector<std::size_t> shape = {static_cast<std::size_t>(n)};
auto& m = meshes[index];
m->shape_ = xt::adapt(dims, n, xt::no_ownership(), shape);
m->n_dimension_ = m->shape_.size();
return 0;
}
//! Get the mesh parameters
extern "C" int
openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n)
{
if (index < 0 || index >= meshes.size()) {
set_errmsg("Index in meshes array is out of bounds.");
return OPENMC_E_OUT_OF_BOUNDS;
}
auto& m = meshes[index];
if (m->lower_left_.dimension() == 0) {
set_errmsg("Mesh parameters have not been set.");
return OPENMC_E_ALLOCATE;
}
*ll = m->lower_left_.data();
*ur = m->upper_right_.data();
*n = m->n_dimension_;
return 0;
}
//! Set the mesh parameters
extern "C" int
openmc_mesh_set_params(int32_t index, int n, const double* ll, const double* ur,
const double* width)
{
if (index < 0 || index >= meshes.size()) {
set_errmsg("Index in meshes array is out of bounds.");
return OPENMC_E_OUT_OF_BOUNDS;
}
auto& m = meshes[index];
std::vector<std::size_t> shape = {static_cast<std::size_t>(n)};
if (ll && ur) {
m->lower_left_ = xt::adapt(ll, n, xt::no_ownership(), shape);
m->upper_right_ = xt::adapt(ur, n, xt::no_ownership(), shape);
m->width_ = (m->upper_right_ - m->lower_left_) / m->shape_;
} else if (ll && width) {
m->lower_left_ = xt::adapt(ll, n, xt::no_ownership(), shape);
m->width_ = xt::adapt(width, n, xt::no_ownership(), shape);
m->upper_right_ = m->lower_left_ + m->shape_ * m->width_;
} else if (ur && width) {
m->upper_right_ = xt::adapt(ur, n, xt::no_ownership(), shape);
m->width_ = xt::adapt(width, n, xt::no_ownership(), shape);
m->lower_left_ = m->upper_right_ - m->shape_ * m->width_;
} else {
set_errmsg("At least two parameters must be specified.");
return OPENMC_E_INVALID_ARGUMENT;
}
return 0;
}
} // namespace openmc

View file

@ -52,6 +52,73 @@ module mesh_header
! Dictionary that maps user IDs to indices in 'meshes'
type(DictIntInt), public :: mesh_dict
interface
function openmc_extend_meshes(n, index_start, index_end) result(err) bind(C)
import C_INT32_T, C_INT
integer(C_INT32_T), value, intent(in) :: n
integer(C_INT32_T), optional, intent(out) :: index_start
integer(C_INT32_T), optional, intent(out) :: index_end
integer(C_INT) :: err
end function openmc_extend_meshes
function openmc_get_mesh_index(id, index) result(err) bind(C)
import C_INT32_T, C_INT
integer(C_INT32_T), value :: id
integer(C_INT32_T), intent(out) :: index
integer(C_INT) :: err
end function openmc_get_mesh_index
function openmc_mesh_get_id(index, id) result(err) bind(C)
import C_INT32_T, C_INT
integer(C_INT32_T), value :: index
integer(C_INT32_T), intent(out) :: id
integer(C_INT) :: err
end function openmc_mesh_get_id
function openmc_mesh_set_id(index, id) result(err) bind(C)
import C_INT32_T, C_INT
integer(C_INT32_T), value, intent(in) :: index
integer(C_INT32_T), value, intent(in) :: id
integer(C_INT) :: err
end function openmc_mesh_set_id
function openmc_mesh_get_dimension(index, dims, n) result(err) bind(C)
import C_INT32_T, C_PTR, C_INT
integer(C_INT32_T), value, intent(in) :: index
type(C_PTR), intent(out) :: dims
integer(C_INT), intent(out) :: n
integer(C_INT) :: err
end function openmc_mesh_get_dimension
function openmc_mesh_set_dimension(index, n, dims) result(err) bind(C)
import C_INT32_T, C_INT
integer(C_INT32_T), value, intent(in) :: index
integer(C_INT), value, intent(in) :: n
integer(C_INT), intent(in) :: dims(n)
integer(C_INT) :: err
end function openmc_mesh_set_dimension
function openmc_mesh_get_params(index, ll, ur, width, n) result(err) bind(C)
import C_INT32_T, C_PTR, C_INT
integer(C_INT32_T), value, intent(in) :: index
type(C_PTR), intent(out) :: ll
type(C_PTR), intent(out) :: ur
type(C_PTR), intent(out) :: width
integer(C_INT), intent(out) :: n
integer(C_INT) :: err
end function openmc_mesh_get_params
function openmc_mesh_set_params(index, n, ll, ur, width) result(err) bind(C)
import C_INT32_T, C_INT, C_DOUBLE
integer(C_INT32_T), value, intent(in) :: index
integer(C_INT), value, intent(in) :: n
real(C_DOUBLE), intent(in), optional :: ll(n)
real(C_DOUBLE), intent(in), optional :: ur(n)
real(C_DOUBLE), intent(in), optional :: width(n)
integer(C_INT) :: err
end function openmc_mesh_set_params
end interface
contains
subroutine regular_from_xml(this, node)
@ -562,215 +629,4 @@ contains
call mesh_dict % clear()
end subroutine free_memory_mesh
!===============================================================================
! C API FUNCTIONS
!===============================================================================
function openmc_extend_meshes(n, index_start, index_end) result(err) bind(C)
! Extend the meshes array by n elements
integer(C_INT32_T), value, intent(in) :: n
integer(C_INT32_T), optional, intent(out) :: index_start
integer(C_INT32_T), optional, intent(out) :: index_end
integer(C_INT) :: err
type(RegularMesh), allocatable :: temp(:) ! temporary meshes array
if (n_meshes == 0) then
! Allocate meshes array
allocate(meshes(n))
else
! Allocate meshes array with increased size
allocate(temp(n_meshes + n))
! Copy original meshes to temporary array
temp(1:n_meshes) = meshes
! Move allocation from temporary array
call move_alloc(FROM=temp, TO=meshes)
end if
! Return indices in meshes array
if (present(index_start)) index_start = n_meshes + 1
if (present(index_end)) index_end = n_meshes + n
n_meshes = n_meshes + n
err = 0
end function openmc_extend_meshes
function openmc_get_mesh_index(id, index) result(err) bind(C)
! Return the index in the meshes array of a mesh with a given ID
integer(C_INT32_T), value :: id
integer(C_INT32_T), intent(out) :: index
integer(C_INT) :: err
if (allocated(meshes)) then
if (mesh_dict % has(id)) then
index = mesh_dict % get(id)
err = 0
else
err = E_INVALID_ID
call set_errmsg("No mesh exists with ID=" // trim(to_str(id)) // ".")
end if
else
err = E_ALLOCATE
call set_errmsg("Memory has not been allocated for meshes.")
end if
end function openmc_get_mesh_index
function openmc_mesh_get_id(index, id) result(err) bind(C)
! Return the ID of a mesh
integer(C_INT32_T), value :: index
integer(C_INT32_T), intent(out) :: id
integer(C_INT) :: err
if (index >= 1 .and. index <= size(meshes)) then
id = meshes(index) % id
err = 0
else
err = E_OUT_OF_BOUNDS
call set_errmsg("Index in meshes array is out of bounds.")
end if
end function openmc_mesh_get_id
function openmc_mesh_set_id(index, id) result(err) bind(C)
! Set the ID of a mesh
integer(C_INT32_T), value, intent(in) :: index
integer(C_INT32_T), value, intent(in) :: id
integer(C_INT) :: err
if (index >= 1 .and. index <= n_meshes) then
meshes(index) % id = id
call mesh_dict % set(id, index)
err = 0
else
err = E_OUT_OF_BOUNDS
call set_errmsg("Index in meshes array is out of bounds.")
end if
end function openmc_mesh_set_id
function openmc_mesh_get_dimension(index, dims, n) result(err) bind(C)
! Get the dimension of a mesh
integer(C_INT32_T), value, intent(in) :: index
type(C_PTR), intent(out) :: dims
integer(C_INT), intent(out) :: n
integer(C_INT) :: err
if (index >= 1 .and. index <= n_meshes) then
dims = C_LOC(meshes(index) % dimension)
n = meshes(index) % n_dimension
err = 0
else
err = E_OUT_OF_BOUNDS
call set_errmsg("Index in meshes array is out of bounds.")
end if
end function openmc_mesh_get_dimension
function openmc_mesh_set_dimension(index, n, dims) result(err) bind(C)
! Set the dimension of a mesh
integer(C_INT32_T), value, intent(in) :: index
integer(C_INT), value, intent(in) :: n
integer(C_INT), intent(in) :: dims(n)
integer(C_INT) :: err
if (index >= 1 .and. index <= n_meshes) then
associate (m => meshes(index))
if (allocated(m % dimension)) deallocate (m % dimension)
if (allocated(m % lower_left)) deallocate (m % lower_left)
if (allocated(m % upper_right)) deallocate (m % upper_right)
if (allocated(m % width)) deallocate (m % width)
m % n_dimension = n
allocate(m % dimension(n))
allocate(m % lower_left(n))
allocate(m % upper_right(n))
allocate(m % width(n))
! Copy dimension
m % dimension(:) = dims
end associate
err = 0
else
err = E_OUT_OF_BOUNDS
call set_errmsg("Index in meshes array is out of bounds.")
end if
end function openmc_mesh_set_dimension
function openmc_mesh_get_params(index, ll, ur, width, n) result(err) bind(C)
! Get the mesh parameters
integer(C_INT32_T), value, intent(in) :: index
type(C_PTR), intent(out) :: ll
type(C_PTR), intent(out) :: ur
type(C_PTR), intent(out) :: width
integer(C_INT), intent(out) :: n
integer(C_INT) :: err
err = 0
if (index >= 1 .and. index <= n_meshes) then
associate (m => meshes(index))
if (allocated(m % lower_left)) then
ll = C_LOC(m % lower_left(1))
ur = C_LOC(m % upper_right(1))
width = C_LOC(m % width(1))
n = m % n_dimension
else
err = E_ALLOCATE
call set_errmsg("Mesh parameters have not been set.")
end if
end associate
else
err = E_OUT_OF_BOUNDS
call set_errmsg("Index in meshes array is out of bounds.")
end if
end function openmc_mesh_get_params
function openmc_mesh_set_params(index, n, ll, ur, width) result(err) bind(C)
! Set the mesh parameters
integer(C_INT32_T), value, intent(in) :: index
integer(C_INT), value, intent(in) :: n
real(C_DOUBLE), intent(in), optional :: ll(n)
real(C_DOUBLE), intent(in), optional :: ur(n)
real(C_DOUBLE), intent(in), optional :: width(n)
integer(C_INT) :: err
err = 0
if (index >= 1 .and. index <= n_meshes) then
associate (m => meshes(index))
if (allocated(m % lower_left)) deallocate (m % lower_left)
if (allocated(m % upper_right)) deallocate (m % upper_right)
if (allocated(m % width)) deallocate (m % width)
allocate(m % lower_left(n))
allocate(m % upper_right(n))
allocate(m % width(n))
if (present(ll) .and. present(ur)) then
m % lower_left(:) = ll
m % upper_right(:) = ur
m % width(:) = (ur - ll) / m % dimension
elseif (present(ll) .and. present(width)) then
m % lower_left(:) = ll
m % width(:) = width
m % upper_right(:) = ll + width * m % dimension
elseif (present(ur) .and. present(width)) then
m % upper_right(:) = ur
m % width(:) = width
m % lower_left(:) = ur - width * m % dimension
else
err = E_INVALID_ARGUMENT
call set_errmsg("At least two parameters must be specified.")
end if
end associate
else
err = E_OUT_OF_BOUNDS
call set_errmsg("Index in meshes array is out of bounds.")
end if
end function openmc_mesh_set_params
end module mesh_header

View file

@ -501,7 +501,7 @@ read_settings_xml()
int temp = std::stoi(get_node_value(root, "entropy_mesh"));
try {
index_entropy_mesh = mesh_map.at(temp);
} catch (std::out_of_range) {
} catch (const std::out_of_range& e) {
std::stringstream msg;
msg << "Mesh " << temp << " specified for Shannon entropy does not exist.";
fatal_error(msg);
@ -550,7 +550,7 @@ read_settings_xml()
auto temp = std::stoi(get_node_value(root, "ufs_mesh"));
try {
index_ufs_mesh = mesh_map.at(temp);
} catch (std::out_of_range) {
} catch (const std::out_of_range& e) {
std::stringstream msg;
msg << "Mesh " << temp << " specified for uniform fission site method "
"does not exist.";