#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; }