Files
FAT-Allocator/benchmarks/benchmarks/XSbench/GridInit.c
2024-12-30 12:54:21 +00:00

236 lines
8.9 KiB
C

#include "XSbench_header.h"
// #include "malloc.h"
#define malloc MALLOCCHERI
#define free FREECHERI
SimulationData grid_init_do_not_profile( Inputs in, int mype )
{
// Structure to hold all allocated simuluation data arrays
SimulationData SD;
// Keep track of how much data we're allocating
size_t nbytes = 0;
// Set the initial seed value
uint64_t seed = 42;
// loop variable
long e = 0;
////////////////////////////////////////////////////////////////////
// Initialize Nuclide Grids
////////////////////////////////////////////////////////////////////
if(mype == 0) printf("Intializing nuclide grids...\n");
// First, we need to initialize our nuclide grid. This comes in the form
// of a flattened 2D array that hold all the information we need to define
// the cross sections for all isotopes in the simulation.
// The grid is composed of "NuclideGridPoint" structures, which hold the
// energy level of the grid point and all associated XS data at that level.
// An array of structures (AOS) is used instead of
// a structure of arrays, as the grid points themselves are accessed in
// a random order, but all cross section interaction channels and the
// energy level are read whenever the gridpoint is accessed, meaning the
// AOS is more cache efficient.
// Initialize Nuclide Grid
SD.length_nuclide_grid = in.n_isotopes * in.n_gridpoints;
SD.nuclide_grid = (NuclideGridPoint *) malloc( SD.length_nuclide_grid * sizeof(NuclideGridPoint));
assert(SD.nuclide_grid != NULL);
nbytes += SD.length_nuclide_grid * sizeof(NuclideGridPoint);
for( int i = 0; i < SD.length_nuclide_grid; i++ )
{
SD.nuclide_grid[i].energy = LCG_random_double(&seed);
SD.nuclide_grid[i].total_xs = LCG_random_double(&seed);
SD.nuclide_grid[i].elastic_xs = LCG_random_double(&seed);
SD.nuclide_grid[i].absorbtion_xs = LCG_random_double(&seed);
SD.nuclide_grid[i].fission_xs = LCG_random_double(&seed);
SD.nuclide_grid[i].nu_fission_xs = LCG_random_double(&seed);
}
// Sort so that each nuclide has data stored in ascending energy order.
for( int i = 0; i < in.n_isotopes; i++ )
qsort( &SD.nuclide_grid[i*in.n_gridpoints], in.n_gridpoints, sizeof(NuclideGridPoint), NGP_compare);
// error debug check
/*
for( int i = 0; i < in.n_isotopes; i++ )
{
printf("NUCLIDE %d ==============================\n", i);
for( int j = 0; j < in.n_gridpoints; j++ )
printf("E%d = %lf\n", j, SD.nuclide_grid[i * in.n_gridpoints + j].energy);
}
*/
////////////////////////////////////////////////////////////////////
// Initialize Acceleration Structure
////////////////////////////////////////////////////////////////////
if( in.grid_type == NUCLIDE )
{
SD.length_unionized_energy_array = 0;
SD.length_index_grid = 0;
}
if( in.grid_type == UNIONIZED )
{
if(mype == 0) printf("Intializing unionized grid...\n");
// Allocate space to hold the union of all nuclide energy data
SD.length_unionized_energy_array = in.n_isotopes * in.n_gridpoints;
SD.unionized_energy_array = (double *) malloc( SD.length_unionized_energy_array * sizeof(double));
assert(SD.unionized_energy_array != NULL );
nbytes += SD.length_unionized_energy_array * sizeof(double);
// Copy energy data over from the nuclide energy grid
for( int i = 0; i < SD.length_unionized_energy_array; i++ )
SD.unionized_energy_array[i] = SD.nuclide_grid[i].energy;
// Sort unionized energy array
qsort( SD.unionized_energy_array, SD.length_unionized_energy_array, sizeof(double), double_compare);
// Allocate space to hold the acceleration grid indices
SD.length_index_grid = SD.length_unionized_energy_array * in.n_isotopes;
SD.index_grid = (int *) malloc( SD.length_index_grid * sizeof(int));
assert(SD.index_grid != NULL);
nbytes += SD.length_index_grid * sizeof(int);
// Generates the double indexing grid
int * idx_low = (int *) calloc( in.n_isotopes, sizeof(int));
assert(idx_low != NULL );
double * energy_high = (double *) malloc( in.n_isotopes * sizeof(double));
assert(energy_high != NULL );
for( int i = 0; i < in.n_isotopes; i++ )
energy_high[i] = SD.nuclide_grid[i * in.n_gridpoints + 1].energy;
for( long e = 0; e < SD.length_unionized_energy_array; e++ )
{
double unionized_energy = SD.unionized_energy_array[e];
for( long i = 0; i < in.n_isotopes; i++ )
{
if( unionized_energy < energy_high[i] )
SD.index_grid[e * in.n_isotopes + i] = idx_low[i];
else if( idx_low[i] == in.n_gridpoints - 2 )
SD.index_grid[e * in.n_isotopes + i] = idx_low[i];
else
{
idx_low[i]++;
SD.index_grid[e * in.n_isotopes + i] = idx_low[i];
energy_high[i] = SD.nuclide_grid[i * in.n_gridpoints + idx_low[i] + 1].energy;
}
}
}
free(idx_low);
free(energy_high);
}
if( in.grid_type == HASH )
{
if(mype == 0) printf("Intializing hash grid...\n");
SD.length_unionized_energy_array = 0;
SD.length_index_grid = in.hash_bins * in.n_isotopes;
SD.index_grid = (int *) malloc( SD.length_index_grid * sizeof(int));
assert(SD.index_grid != NULL);
nbytes += SD.length_index_grid * sizeof(int);
double du = 1.0 / in.hash_bins;
// For each energy level in the hash table
#pragma omp parallel for
for( e = 0; e < in.hash_bins; e++ )
{
double energy = e * du;
// We need to determine the bounding energy levels for all isotopes
for( long i = 0; i < in.n_isotopes; i++ )
{
SD.index_grid[e * in.n_isotopes + i] = grid_search_nuclide( in.n_gridpoints, energy, SD.nuclide_grid + i * in.n_gridpoints, 0, in.n_gridpoints-1);
}
}
}
////////////////////////////////////////////////////////////////////
// Initialize Materials and Concentrations
////////////////////////////////////////////////////////////////////
if(mype == 0) printf("Intializing material data...\n");
// Set the number of nuclides in each material
SD.num_nucs = load_num_nucs(in.n_isotopes);
SD.length_num_nucs = 12; // There are always 12 materials in XSBench
// Intialize the flattened 2D grid of material data. The grid holds
// a list of nuclide indices for each of the 12 material types. The
// grid is allocated as a full square grid, even though not all
// materials have the same number of nuclides.
SD.mats = load_mats(SD.num_nucs, in.n_isotopes, &SD.max_num_nucs);
SD.length_mats = SD.length_num_nucs * SD.max_num_nucs;
// Intialize the flattened 2D grid of nuclide concentration data. The grid holds
// a list of nuclide concentrations for each of the 12 material types. The
// grid is allocated as a full square grid, even though not all
// materials have the same number of nuclides.
SD.concs = load_concs(SD.num_nucs, SD.max_num_nucs);
SD.length_concs = SD.length_mats;
// Allocate and initialize replicas
#ifdef AML
// num_nucs
aml_replicaset_hwloc_create(&(SD.num_nucs_replica),
SD.length_num_nucs * sizeof(*(SD.num_nucs)),
HWLOC_OBJ_CORE,
HWLOC_DISTANCES_KIND_FROM_OS |
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
nbytes += (SD.num_nucs_replica)->n * (SD.num_nucs_replica)->size;
aml_replicaset_init(SD.num_nucs_replica, SD.num_nucs);
// concs
aml_replicaset_hwloc_create(&(SD.concs_replica),
SD.length_concs * sizeof(*(SD.concs)),
HWLOC_OBJ_CORE,
HWLOC_DISTANCES_KIND_FROM_OS |
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
nbytes += (SD.concs_replica)->n * (SD.concs_replica)->size;
aml_replicaset_init(SD.concs_replica, SD.concs);
// unionized_energy_array
if( in.grid_type == UNIONIZED ){
aml_replicaset_hwloc_create(&(SD.unionized_energy_array_replica),
SD.length_unionized_energy_array * sizeof(*(SD.unionized_energy_array)),
HWLOC_OBJ_CORE,
HWLOC_DISTANCES_KIND_FROM_OS |
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
nbytes += (SD.unionized_energy_array_replica)->n * (SD.unionized_energy_array_replica)->size;
aml_replicaset_init(SD.unionized_energy_array_replica, SD.unionized_energy_array);
}
// index grid
if( in.grid_type == UNIONIZED || in.grid_type == HASH ){
aml_replicaset_hwloc_create(&(SD.index_grid_replica),
SD.length_index_grid * sizeof(*(SD.index_grid)),
HWLOC_OBJ_CORE,
HWLOC_DISTANCES_KIND_FROM_OS |
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
nbytes += (SD.index_grid_replica)->n * (SD.index_grid_replica)->size;
aml_replicaset_init(SD.index_grid_replica, SD.index_grid);
}
// nuclide grid
aml_replicaset_hwloc_create(&(SD.nuclide_grid_replica),
SD.length_nuclide_grid * sizeof(*(SD.nuclide_grid)),
HWLOC_OBJ_CORE,
HWLOC_DISTANCES_KIND_FROM_OS |
HWLOC_DISTANCES_KIND_MEANS_LATENCY);
nbytes += (SD.nuclide_grid_replica)->n * (SD.nuclide_grid_replica)->size;
aml_replicaset_init(SD.nuclide_grid_replica, SD.nuclide_grid);
#endif
if(mype == 0) printf("Intialization complete. Allocated %.0lf MB of data.\n", nbytes/1024.0/1024.0 );
return SD;
}