blob: 92b3a10e49862b4b5a54576add260438f86570be [file] [log] [blame]
#include "XSbench_header.h"
// Calculates the microscopic cross section for a given nuclide & energy
void calculate_micro_xs( double p_energy, int nuc, long n_isotopes,
long n_gridpoints,
GridPoint * restrict energy_grid,
NuclideGridPoint ** restrict nuclide_grids,
int idx, double * restrict xs_vector ){
// Variables
double f;
NuclideGridPoint * low, * high;
// pull ptr from energy grid and check to ensure that
// we're not reading off the end of the nuclide's grid
if( energy_grid[idx].xs_ptrs[nuc] == n_gridpoints - 1 )
low = &nuclide_grids[nuc][energy_grid[idx].xs_ptrs[nuc] - 1];
else
low = &nuclide_grids[nuc][energy_grid[idx].xs_ptrs[nuc]];
high = low + 1;
// calculate the re-useable interpolation factor
f = (high->energy - p_energy) / (high->energy - low->energy);
// Total XS
xs_vector[0] = high->total_xs - f * (high->total_xs - low->total_xs);
// Elastic XS
xs_vector[1] = high->elastic_xs - f * (high->elastic_xs - low->elastic_xs);
// Absorbtion XS
xs_vector[2] = high->absorbtion_xs - f * (high->absorbtion_xs - low->absorbtion_xs);
// Fission XS
xs_vector[3] = high->fission_xs - f * (high->fission_xs - low->fission_xs);
// Nu Fission XS
xs_vector[4] = high->nu_fission_xs - f * (high->nu_fission_xs - low->nu_fission_xs);
//test
/*
if( omp_get_thread_num() == 0 )
{
printf("Lookup: Energy = %lf, nuc = %d\n", p_energy, nuc);
printf("e_h = %lf e_l = %lf\n", high->energy , low->energy);
printf("xs_h = %lf xs_l = %lf\n", high->elastic_xs, low->elastic_xs);
printf("total_xs = %lf\n\n", xs_vector[1]);
}
*/
}
// Calculates macroscopic cross section based on a given material & energy
void calculate_macro_xs( double p_energy, int mat, long n_isotopes,
long n_gridpoints, int * restrict num_nucs,
double ** restrict concs,
GridPoint * restrict energy_grid,
NuclideGridPoint ** restrict nuclide_grids,
int ** restrict mats,
double * restrict macro_xs_vector ){
double xs_vector[5];
int p_nuc; // the nuclide we are looking up
long idx = 0;
double conc; // the concentration of the nuclide in the material
// cleans out macro_xs_vector
for( int k = 0; k < 5; k++ )
macro_xs_vector[k] = 0;
// binary search for energy on unionized energy grid (UEG)
idx = grid_search( n_isotopes * n_gridpoints, p_energy,
energy_grid);
// Once we find the pointer array on the UEG, we can pull the data
// from the respective nuclide grids, as well as the nuclide
// concentration data for the material
// Each nuclide from the material needs to have its micro-XS array
// looked up & interpolatied (via calculate_micro_xs). Then, the
// micro XS is multiplied by the concentration of that nuclide
// in the material, and added to the total macro XS array.
for( int j = 0; j < num_nucs[mat]; j++ )
{
p_nuc = mats[mat][j];
conc = concs[mat][j];
calculate_micro_xs( p_energy, p_nuc, n_isotopes,
n_gridpoints, energy_grid,
nuclide_grids, idx, xs_vector );
for( int k = 0; k < 5; k++ )
macro_xs_vector[k] += xs_vector[k] * conc;
}
//test
/*
for( int k = 0; k < 5; k++ )
printf("Energy: %lf, Material: %d, XSVector[%d]: %lf\n",
p_energy, mat, k, macro_xs_vector[k]);
*/
}
// (fixed) binary search for energy on unionized energy grid
// returns lower index
long grid_search( long n, double quarry, GridPoint * A)
{
long lowerLimit = 0;
long upperLimit = n-1;
long examinationPoint;
long length = upperLimit - lowerLimit;
while( length > 1 )
{
examinationPoint = lowerLimit + ( length / 2 );
if( A[examinationPoint].energy > quarry )
upperLimit = examinationPoint;
else
lowerLimit = examinationPoint;
length = upperLimit - lowerLimit;
}
return lowerLimit;
}