Implemented sample_scatter in C++

This commit is contained in:
Adam G Nelson 2018-06-10 14:23:08 -04:00
parent 59c4bc3fc4
commit 6c8de73e3e
8 changed files with 156 additions and 69 deletions

View file

@ -10,7 +10,6 @@
namespace openmc {
typedef std::array<double, 3> dir_arr;
typedef std::vector<double> double_1dvec;
typedef std::vector<std::vector<double> > double_2dvec;
typedef std::vector<std::vector<std::vector<double> > > double_3dvec;

View file

@ -24,6 +24,13 @@ void Mgxs::init(const std::string& in_name, const double in_awr,
azimuthal = in_azimuthal;
n_pol = polar.size();
n_azi = azimuthal.size();
index_temp = 0;
last_sqrtkT = 0.;
index_pol = 0;
index_azi = 0;
last_uvw[0] = 1.;
last_uvw[1] = 0.;
last_uvw[2] = 0.;
}
@ -383,7 +390,8 @@ void Mgxs::combine(std::vector<Mgxs*>& micros, double_1dvec& scalars,
}
double Mgxs::get_xs(const char* xstype, int gin, int* gout, double* mu, int* dg)
double Mgxs::get_xs(const char* xstype, const int gin, int* gout, double* mu,
int* dg)
{
// This method assumes that the temperature and angle indices are set
double val;
@ -469,7 +477,8 @@ double Mgxs::get_xs(const char* xstype, int gin, int* gout, double* mu, int* dg)
}
void Mgxs::sample_fission_energy(int gin, double nu_fission, int& dg, int& gout)
void Mgxs::sample_fission_energy(const int gin, const double nu_fission,
int& dg, int& gout)
{
// This method assumes that the temperature and angle indices are set
// Find the probability of having a prompt neutron
@ -525,8 +534,7 @@ void Mgxs::sample_fission_energy(int gin, double nu_fission, int& dg, int& gout)
}
void Mgxs::sample_scatter(dir_arr& uvw, int gin, int& gout, double& mu,
double& wgt)
void Mgxs::sample_scatter(const int gin, int& gout, double& mu, double& wgt)
{
// This method assumes that the temperature and angle indices are set
// Sample the data
@ -534,8 +542,8 @@ void Mgxs::sample_scatter(dir_arr& uvw, int gin, int& gout, double& mu,
}
void Mgxs::calculate_xs(int gin, double sqrtkT, dir_arr& uvw, double& total_xs,
double& abs_xs, double& nu_fiss_xs)
void Mgxs::calculate_xs(const int gin, const double sqrtkT, const double uvw[3],
double& total_xs, double& abs_xs, double& nu_fiss_xs)
{
// Set our indices
set_temperature_index(sqrtkT);
@ -543,10 +551,14 @@ void Mgxs::calculate_xs(int gin, double sqrtkT, dir_arr& uvw, double& total_xs,
total_xs = xs[index_temp].total[index_pol][index_azi][gin];
abs_xs = xs[index_temp].absorption[index_pol][index_azi][gin];
// nu-fission is made up of the prompt and all the delayed nu_fission data
nu_fiss_xs = xs[index_temp].prompt_nu_fission[index_pol][index_azi][gin];
for (auto& val : xs[index_temp].delayed_nu_fission[index_pol][index_azi][gin]) {
nu_fiss_xs += val;
if (fissionable) {
// nu-fission is made up of the prompt and all the delayed nu_fission data
nu_fiss_xs = xs[index_temp].prompt_nu_fission[index_pol][index_azi][gin];
for (auto& val : xs[index_temp].delayed_nu_fission[index_pol][index_azi][gin]) {
nu_fiss_xs += val;
}
} else {
nu_fiss_xs = 0.;
}
}
@ -568,7 +580,7 @@ bool Mgxs::equiv(const Mgxs& that)
}
inline void Mgxs::set_temperature_index(double sqrtkT)
inline void Mgxs::set_temperature_index(const double sqrtkT)
{
// See if we need to find the new index
if (sqrtkT != last_sqrtkT) {
@ -588,27 +600,30 @@ inline void Mgxs::set_temperature_index(double sqrtkT)
}
inline void Mgxs::set_angle_index(dir_arr& uvw)
inline void Mgxs::set_angle_index(const double uvw[3])
{
// See if we need to find the new index
if (uvw != last_uvw) {
if ((uvw[0] != last_uvw[0]) || (uvw[1] != last_uvw[1]) ||
(uvw[2] != last_uvw[2])) {
// convert uvw to polar and azimuthal angles
double my_pol = std::acos(uvw[2]);
double my_azi = std::atan2(uvw[1], uvw[0]);
// Find the location, assuming equal-bin angles
double delta_angle = PI / n_pol;
index_pol = std::floor(my_pol / delta_angle + 1.);
delta_angle = PI / n_azi;
index_azi = std::floor((my_azi + PI) / delta_angle + 1.);
index_pol = std::floor(my_pol / delta_angle);
delta_angle = 2. * PI / n_azi;
index_azi = std::floor((my_azi + PI) / delta_angle);
// store this direction as the last one used
last_uvw = uvw;
last_uvw[0] = uvw[0];
last_uvw[1] = uvw[1];
last_uvw[2] = uvw[2];
}
}
//==============================================================================
// Mgxs data loading methods
// Mgxs data loading interface methods
//==============================================================================
void add_mgxs(hid_t file_id, char* name, int energy_groups,
@ -680,4 +695,25 @@ void create_macro_xs(char* mat_name, const int n_nuclides,
macro_xs.push_back(macro);
}
//==============================================================================
// Mgxs tracking/transport/tallying interface methods
//==============================================================================
void calculate_xs(const int i_mat, const int gin, const double sqrtkT,
const double uvw[3], double& total_xs, double& abs_xs, double& nu_fiss_xs)
{
macro_xs[i_mat - 1].calculate_xs(gin - 1, sqrtkT, uvw, total_xs, abs_xs,
nu_fiss_xs);
}
void scatter(const int i_mat, const int gin, int& gout, double& mu,
double& wgt, double uvw[3])
{
int gout_c = gout - 1;
macro_xs[i_mat - 1].sample_scatter(gin - 1, gout_c, mu, wgt);
gout = gout_c + 1;
rotate_angle_c(uvw, mu, nullptr);
}
} // namespace openmc

View file

@ -44,7 +44,7 @@ class Mgxs {
int index_azi;
double_1dvec polar;
double_1dvec azimuthal;
dir_arr last_uvw;
double last_uvw[3];
void _metadata_from_hdf5(const hid_t xs_id, const int in_num_groups,
const int in_num_delayed_groups, double_1dvec& temperature,
int& method, const double tolerance, int_1dvec& temps_to_read,
@ -66,16 +66,16 @@ class Mgxs {
double_1dvec& temperature, int& method, double tolerance,
int max_order, bool legendre_to_tabular,
int legendre_to_tabular_points);
double get_xs(const char* xstype, int gin, int* gout, double* mu,
double get_xs(const char* xstype, const int gin, int* gout, double* mu,
int* dg);
void sample_fission_energy(int gin, double nu_fission, int& dg, int& gout);
void sample_scatter(dir_arr& uvw, int gin, int& gout, double& mu,
double& wgt);
void calculate_xs(int gin, double sqrtkT, dir_arr& uvw, double& total_xs,
double& abs_xs, double& nu_fiss_xs);
void sample_fission_energy(const int gin, const double nu_fission,
int& dg, int& gout);
void sample_scatter(const int gin, int& gout, double& mu, double& wgt);
void calculate_xs(const int gin, const double sqrtkT, const double uvw[3],
double& total_xs, double& abs_xs, double& nu_fiss_xs);
bool equiv(const Mgxs& that);
inline void set_temperature_index(double sqrtkT);
inline void set_angle_index(dir_arr& uvw);
inline void set_temperature_index(const double sqrtkT);
inline void set_angle_index(const double uvw[3]);
};
extern "C" void add_mgxs(hid_t file_id, char* name, int energy_groups,
@ -89,6 +89,13 @@ extern "C" void create_macro_xs(char* mat_name, const int n_nuclides,
const int i_nuclides[], const int n_temps, const double temps[],
const double atom_densities[], int& method, const double tolerance);
extern "C" void calculate_xs(const int i_mat, const int gin,
const double sqrtkT, const double uvw[3], double& total_xs,
double& abs_xs, double& nu_fiss_xs);
extern "C" void scatter(const int i_mat, const int gin, int& gout, double& mu,
double& wgt, double uvw[3]);
// Storage for the MGXS data
std::vector<Mgxs> nuclides_MG;

View file

@ -166,10 +166,10 @@ module nuclide_header
!===============================================================================
type MaterialMacroXS
real(8) :: total ! macroscopic total xs
real(8) :: absorption ! macroscopic absorption xs
real(8) :: fission ! macroscopic fission xs
real(8) :: nu_fission ! macroscopic production xs
real(C_DOUBLE) :: total ! macroscopic total xs
real(C_DOUBLE) :: absorption ! macroscopic absorption xs
real(C_DOUBLE) :: fission ! macroscopic fission xs
real(C_DOUBLE) :: nu_fission ! macroscopic production xs
end type MaterialMacroXS
!===============================================================================

View file

@ -22,6 +22,20 @@ module physics_mg
implicit none
interface
subroutine scatter_c(i_mat, gin, gout, mu, wgt, uvw) &
bind(C, name='scatter')
use ISO_C_BINDING
implicit none
integer(C_INT), value, intent(in) :: i_mat
integer(C_INT), value, intent(in) :: gin
integer(C_INT), intent(inout) :: gout
real(C_DOUBLE), intent(inout) :: mu
real(C_DOUBLE), intent(inout) :: wgt
real(C_DOUBLE), intent(inout) :: uvw(1:3)
end subroutine scatter_c
end interface
contains
!===============================================================================
@ -143,16 +157,18 @@ contains
type(Particle), intent(inout) :: p
call macro_xs(p % material) % obj % sample_scatter(p % coord(1) % uvw, &
p % last_g, p % g, &
p % mu, p % wgt)
! call macro_xs(p % material) % obj % sample_scatter(p % coord(1) % uvw, &
! p % last_g, p % g, p % mu, p % wgt)
! Convert change in angle (mu) to new direction
! p % coord(1) % uvw = rotate_angle(p % coord(1) % uvw, p % mu)
call scatter_c(p % material, p % last_g, p % g, p % mu, p % wgt, &
p % coord(1) % uvw)
! Update energy value for downstream compatability (in tallying)
p % E = energy_bin_avg(p % g)
! Convert change in angle (mu) to new direction
p % coord(1) % uvw = rotate_angle(p % coord(1) % uvw, p % mu)
! Set event component
p % event = EVENT_SCATTER

View file

@ -44,7 +44,8 @@ void ScattData::sample_energy(int gin, int& gout, int& i_gout)
{
// Sample the outgoing group
double xi = prn();
i_gout = 0; //TODO: + 1?
i_gout = 0;
gout = gmin[gin];
double prob = energy[gin][i_gout];
while((prob < xi) && (gout < gmax[gin])) {
@ -247,7 +248,7 @@ void ScattDataLegendre::sample(int gin, int& gout, double& mu, double& wgt)
}
void ScattDataLegendre::combine(std::vector<ScattData*> those_scatts,
void ScattDataLegendre::combine(std::vector<ScattData*>& those_scatts,
double_1dvec& scalars)
{
// Find the max order in the data set and make sure we can combine the sets
@ -294,6 +295,7 @@ void ScattDataLegendre::combine(std::vector<ScattData*> those_scatts,
for (int gin = 0; gin < groups; gin++) {
// Only spend time adding that's gmin to gmax data since the rest will
// be zeros
int i_gout = 0;
for (int gout = that->gmin[gin]; gout <= that->gmax[gin]; gout++) {
// Do the scattering matrix
for (int l = 0; l < max_order; l++) {
@ -301,13 +303,14 @@ void ScattDataLegendre::combine(std::vector<ScattData*> those_scatts,
}
// Incorporate that's contribution to the multiplicity matrix data
double nuscatt = that->scattxs[gin] * that->energy[gin][gout];
double nuscatt = that->scattxs[gin] * that->energy[gin][i_gout];
mult_numer[gin][gout] += scalars[i] * nuscatt;
if (that->mult[gin][gout] > 0.) {
mult_denom[gin][gout] += scalars[i] * nuscatt / that->mult[gin][gout];
if (that->mult[gin][i_gout] > 0.) {
mult_denom[gin][gout] += scalars[i] * nuscatt / that->mult[gin][i_gout];
} else {
mult_denom[gin][gout] += scalars[i];
}
i_gout++;
}
}
}
@ -336,14 +339,14 @@ void ScattDataLegendre::combine(std::vector<ScattData*> those_scatts,
for (gmin_ = 0; gmin_ < groups; gmin_++) {
bool non_zero = std::all_of(this_matrix[gin][gmin_].begin(),
this_matrix[gin][gmin_].end(),
[](double val){return val > 0.;});
[](double val){return val != 0.;});
if (non_zero) break;
}
int gmax_;
for (gmax_ = groups - 1; gmax_ >= 0; gmax_--) {
bool non_zero = std::all_of(this_matrix[gin][gmax_].begin(),
this_matrix[gin][gmax_].end(),
[](double val){return val > 0.;});
[](double val){return val != 0.;});
if (non_zero) break;
}
@ -425,6 +428,7 @@ void ScattDataHistogram::init(int_1dvec& in_gmin, int_1dvec& in_gmax,
for (int i_gout = 0; i_gout < num_groups; i_gout++) {
double norm = std::accumulate(matrix[gin][i_gout].begin(),
matrix[gin][i_gout].end(), 0.);
in_energy[gin][i_gout] = norm;
if (norm != 0.) {
for (auto& n : matrix[gin][i_gout]) n /= norm;
}
@ -440,7 +444,7 @@ void ScattDataHistogram::init(int_1dvec& in_gmin, int_1dvec& in_gmax,
dmu = 2. / order;
mu[0] = -1.;
for (int imu = 1; imu < order; imu++) {
mu[imu] = -1. + (imu - 1) * dmu;
mu[imu] = -1. + imu * dmu;
}
// Calculate f(mu) and integrate it so we can avoid rejection sampling
@ -507,7 +511,7 @@ void ScattDataHistogram::sample(int gin, int& gout, double& mu, double& wgt)
int imu;
if (xi < dist[gin][i_gout][0]) {
imu = 1;
imu = 0;
} else {
// TODO lower_bound? + 1?
imu = std::upper_bound(dist[gin][i_gout].begin(),
@ -551,7 +555,7 @@ double_3dvec ScattDataHistogram::get_matrix(int max_order)
}
void ScattDataHistogram::combine(std::vector<ScattData*> those_scatts,
void ScattDataHistogram::combine(std::vector<ScattData*>& those_scatts,
double_1dvec& scalars)
{
// Find the max order in the data set and make sure we can combine the sets
@ -600,6 +604,7 @@ void ScattDataHistogram::combine(std::vector<ScattData*> those_scatts,
for (int gin = 0; gin < groups; gin++) {
// Only spend time adding that's gmin to gmax data since the rest will
// be zeros
int i_gout = 0;
for (int gout = that->gmin[gin]; gout <= that->gmax[gin]; gout++) {
// Do the scattering matrix
for (int l = 0; l < max_order; l++) {
@ -607,13 +612,14 @@ void ScattDataHistogram::combine(std::vector<ScattData*> those_scatts,
}
// Incorporate that's contribution to the multiplicity matrix data
double nuscatt = that->scattxs[gin] * that->energy[gin][gout];
double nuscatt = that->scattxs[gin] * that->energy[gin][i_gout];
mult_numer[gin][gout] += scalars[i] * nuscatt;
if (that->mult[gin][gout] > 0.) {
mult_denom[gin][gout] += scalars[i] * nuscatt / that->mult[gin][gout];
if (that->mult[gin][i_gout] > 0.) {
mult_denom[gin][gout] += scalars[i] * nuscatt / that->mult[gin][i_gout];
} else {
mult_denom[gin][gout] += scalars[i];
}
i_gout++;
}
}
}
@ -642,14 +648,14 @@ void ScattDataHistogram::combine(std::vector<ScattData*> those_scatts,
for (gmin_ = 0; gmin_ < groups; gmin_++) {
bool non_zero = std::all_of(this_matrix[gin][gmin_].begin(),
this_matrix[gin][gmin_].end(),
[](double val){return val > 0.;});
[](double val){return val != 0.;});
if (non_zero) break;
}
int gmax_;
for (gmax_ = groups - 1; gmax_ >= 0; gmax_--) {
bool non_zero = std::all_of(this_matrix[gin][gmax_].begin(),
this_matrix[gin][gmax_].end(),
[](double val){return val > 0.;});
[](double val){return val != 0.;});
if (non_zero) break;
}
@ -695,7 +701,7 @@ void ScattDataTabular::init(int_1dvec& in_gmin, int_1dvec& in_gmax,
dmu = 2. / (order - 1);
mu[0] = -1.;
for (int imu = 1; imu < order - 1; imu++) {
mu[imu] = -1. + (imu - 1) * dmu;
mu[imu] = -1. + imu * dmu;
}
mu[order - 1] = 1.;
@ -724,9 +730,7 @@ void ScattDataTabular::init(int_1dvec& in_gmin, int_1dvec& in_gmax,
norm += 0.5 * dmu * (matrix[gin][i_gout][imu - 1] +
matrix[gin][i_gout][imu]);
}
if (norm != 0.) {
for (auto& n : matrix[gin][i_gout]) n /= norm;
}
in_energy[gin][i_gout] = norm;
}
}
@ -806,14 +810,14 @@ void ScattDataTabular::sample(int gin, int& gout, double& mu, double& wgt)
double c_k = dist[gin][i_gout][0];
int k;
for (k = 0; k < NP - 2; k++) {
for (k = 0; k < NP - 1; k++) {
double c_k1 = dist[gin][i_gout][k + 1];
if (xi < c_k1) break;
c_k = c_k1;
}
// Check to make sure k is <= NP - 1
k = std::min(k, NP - 1);
k = std::min(k, NP - 2);
// Find the pdf values we want
double p0 = fmu[gin][i_gout][k];
@ -861,7 +865,7 @@ double_3dvec ScattDataTabular::get_matrix(int max_order)
return matrix;
}
void ScattDataTabular::combine(std::vector<ScattData*> those_scatts,
void ScattDataTabular::combine(std::vector<ScattData*>& those_scatts,
double_1dvec& scalars)
{
// Find the max order in the data set and make sure we can combine the sets
@ -910,6 +914,7 @@ void ScattDataTabular::combine(std::vector<ScattData*> those_scatts,
for (int gin = 0; gin < groups; gin++) {
// Only spend time adding that's gmin to gmax data since the rest will
// be zeros
int i_gout = 0;
for (int gout = that->gmin[gin]; gout <= that->gmax[gin]; gout++) {
// Do the scattering matrix
for (int l = 0; l < max_order; l++) {
@ -917,13 +922,14 @@ void ScattDataTabular::combine(std::vector<ScattData*> those_scatts,
}
// Incorporate that's contribution to the multiplicity matrix data
double nuscatt = that->scattxs[gin] * that->energy[gin][gout];
double nuscatt = that->scattxs[gin] * that->energy[gin][i_gout];
mult_numer[gin][gout] += scalars[i] * nuscatt;
if (that->mult[gin][gout] > 0.) {
mult_denom[gin][gout] += scalars[i] * nuscatt / that->mult[gin][gout];
if (that->mult[gin][i_gout] > 0.) {
mult_denom[gin][gout] += scalars[i] * nuscatt / that->mult[gin][i_gout];
} else {
mult_denom[gin][gout] += scalars[i];
}
i_gout++;
}
}
}
@ -952,14 +958,14 @@ void ScattDataTabular::combine(std::vector<ScattData*> those_scatts,
for (gmin_ = 0; gmin_ < groups; gmin_++) {
bool non_zero = std::all_of(this_matrix[gin][gmin_].begin(),
this_matrix[gin][gmin_].end(),
[](double val){return val > 0.;});
[](double val){return val != 0.;});
if (non_zero) break;
}
int gmax_;
for (gmax_ = groups - 1; gmax_ >= 0; gmax_--) {
bool non_zero = std::all_of(this_matrix[gin][gmax_].begin(),
this_matrix[gin][gmax_].end(),
[](double val){return val > 0.;});
[](double val){return val != 0.;});
if (non_zero) break;
}

View file

@ -41,7 +41,7 @@ class ScattData {
double get_xs(const char* xstype, int gin, int* gout, double* mu);
void generic_init(int order, int_1dvec in_gmin, int_1dvec in_gmax,
double_2dvec in_energy, double_2dvec in_mult);
virtual void combine(std::vector<ScattData*> those_scatts,
virtual void combine(std::vector<ScattData*>& those_scatts,
double_1dvec& scalars) = 0;
virtual int get_order() = 0;
virtual double_3dvec get_matrix(int max_order) = 0;
@ -59,7 +59,7 @@ class ScattDataLegendre: public ScattData {
void update_max_val();
double calc_f(int gin, int gout, double mu);
void sample(int gin, int& gout, double& mu, double& wgt);
void combine(std::vector<ScattData*> those_scatts, double_1dvec& scalars);
void combine(std::vector<ScattData*>& those_scatts, double_1dvec& scalars);
int get_order() {return dist[0][0].size() - 1;};
double_3dvec get_matrix(int max_order);
};
@ -74,7 +74,7 @@ class ScattDataHistogram: public ScattData {
double_3dvec& coeffs);
double calc_f(int gin, int gout, double mu);
void sample(int gin, int& gout, double& mu, double& wgt);
void combine(std::vector<ScattData*> those_scatts, double_1dvec& scalars);
void combine(std::vector<ScattData*>& those_scatts, double_1dvec& scalars);
int get_order() {return dist[0][0].size();};
double_3dvec get_matrix(int max_order);
};
@ -91,7 +91,7 @@ class ScattDataTabular: public ScattData {
double_3dvec& coeffs);
double calc_f(int gin, int gout, double mu);
void sample(int gin, int& gout, double& mu, double& wgt);
void combine(std::vector<ScattData*> those_scatts, double_1dvec& scalars);
void combine(std::vector<ScattData*>& those_scatts, double_1dvec& scalars);
int get_order() {return dist[0][0].size();};
double_3dvec get_matrix(int max_order);
};

View file

@ -1,5 +1,7 @@
module tracking
use, intrinsic :: ISO_C_BINDING
use constants
use error, only: warning, write_message
use geometry_header, only: cells
@ -27,6 +29,21 @@ module tracking
implicit none
interface
subroutine calculate_xs_c(i_mat, gin, sqrtkT, uvw, total_xs, abs_xs, &
nu_fiss_xs) bind(C, name='calculate_xs')
use ISO_C_BINDING
implicit none
integer(C_INT), value, intent(in) :: i_mat
integer(C_INT), value, intent(in) :: gin
real(C_DOUBLE), value, intent(in) :: sqrtkT
real(C_DOUBLE), intent(in) :: uvw(1:3)
real(C_DOUBLE), intent(inout) :: total_xs
real(C_DOUBLE), intent(inout) :: abs_xs
real(C_DOUBLE), intent(inout) :: nu_fiss_xs
end subroutine calculate_xs_c
end interface
contains
!===============================================================================
@ -112,8 +129,14 @@ contains
end if
else
! Get the MG data
!!TODO: Remove Fortran call - needed until I'm done replacing Fortran
!!with C++ code because it sets index_temp
call macro_xs(p % material) % obj % calculate_xs(p % g, p % sqrtkT, &
p % coord(p % n_coord) % uvw, material_xs)
call calculate_xs_c(p % material, p % g, p % sqrtkT, &
p % coord(p % n_coord) % uvw, material_xs % total, &
material_xs % absorption, material_xs % nu_fission)
! Finally, update the particle group while we have already checked
! for if multi-group