blob: d66ca0fcc5cc77a2f7bdf5010d8ea6655116c192 [file] [log] [blame]
#include"SimpleMOC_header.h"
// generates a random number between 0 and 1
float urand(void)
{
return (float)rand() / (float)RAND_MAX;
}
/* generates a random number from a normal distribution of a
* given mean and standard deviation (Box-Muller) */
float nrand(float mean, float sigma)
{
// generate two random numbers
float rand1 = urand();
float rand2 = urand();
/* use first for "exponential part" and second for
* "azimuthal part" to create a standard normal random number */
float x = sqrt( -2 * log(rand1) ) * cos( 2 * M_PI * rand2);
// NOTE: We can generate a second random number if neeeded
// y = sqrt(-2*log(rand1)) * sin( 2 * M_PI * rand2);
// shift random number to appropriate normal distribution and return
return x * sigma + mean;
}
// pairwise summation for long arrays
float pairwise_sum( float * vector, long size ){
float sum = 0;
// Base case: perform summation if size <= 16
if( size <= 16)
for( int i = 0; i < size; i++ )
sum += vector[i];
else
{
// otherwise, split
sum = pairwise_sum( &vector[0], size/2 ) +
pairwise_sum( &vector[size/2], size - size/2 );
}
return sum;
}
// Builds a table of exponential values for linear interpolation
Table buildExponentialTable( float precision, float maxVal )
{
// define table
Table table;
// compute number of arry values
int N = (int) ( maxVal * sqrt(1.0 / ( 8.0 * precision * 0.01 ) ) );
// compute spacing
float dx = maxVal / (float) N;
// allocate an array to store information
float * tableVals = malloc( (2 * N ) * sizeof(float) );
// store linear segment information (slope and y-intercept)
for( int n = 0; n < N; n++ )
{
// compute slope and y-intercept for ( 1 - exp(-x) )
float exponential = exp( - n * dx );
tableVals[ 2*n ] = - exponential;
tableVals[ 2*n + 1 ] = 1 + ( n * dx - 1 ) * exponential;
}
// assign data to table
table.dx = dx;
table.values = tableVals;
table.maxVal = maxVal - table.dx;
table.N = N;
return table;
}
// Timer function. Depends on if compiled with MPI, openmp, or vanilla
double get_time(void)
{
#ifdef MPI
return MPI_Wtime();
#endif
#ifdef OPENMP
return omp_get_wtime();
#endif
time_t time;
time = clock();
return (double) time / (double) CLOCKS_PER_SEC;
}
// Memory Usage Estimator
size_t est_mem_usage( Input I )
{
size_t nbytes = 0;
int z_stacked = (int) ( I.height / (I.axial_z_sep *
I.decomp_assemblies_ax) );
long n_xs_regions = I.n_source_regions_per_node / 8;
nbytes += I.ntracks_2D * sizeof(Track2D);
nbytes += I.segments_per_track * I.ntracks_2D * sizeof(Segment);
nbytes += I.ntracks_2D * sizeof(Track **);
nbytes += I.ntracks_2D * I.n_polar_angles * sizeof(Track *);
nbytes += I.ntracks * sizeof(Track);
nbytes += I.ntracks_2D * I.n_polar_angles * z_stacked
* I.n_egroups * sizeof(float) * 2;
nbytes += I.n_source_regions_per_node * sizeof(Source);
nbytes += n_xs_regions * sizeof(float **);
nbytes += n_xs_regions * sizeof(float **);
nbytes += n_xs_regions * I.n_egroups * I.n_egroups * sizeof(float);
nbytes += n_xs_regions * sizeof(float **);
nbytes += n_xs_regions * I.n_egroups * sizeof(float *);
nbytes += n_xs_regions * I.n_egroups * 3 * sizeof(float);
nbytes += I.n_source_regions_per_node * sizeof(float **);
nbytes += I.n_source_regions_per_node * I.fai * sizeof(float *);
nbytes += I.n_source_regions_per_node * sizeof(float **);
nbytes += I.n_source_regions_per_node * I.fai * sizeof(float *);
nbytes += I.n_source_regions_per_node * I.fai * I.n_egroups
* sizeof(float);
// 2way tracking memory
nbytes += I.nthreads * I.z_stacked * sizeof(double *);
nbytes += I.nthreads * I.z_stacked * sizeof(Source**);
nbytes += I.nthreads * I.z_stacked * sizeof(int);
nbytes += I.nthreads * I.z_stacked * sizeof(int);
nbytes += I.nthreads * I.z_stacked * 2 * I.segments_per_track
* sizeof(double);
nbytes += I.nthreads * I.z_stacked * 2 * I.segments_per_track
* sizeof(Source *);
// MPI Buffers
#ifdef MPI
nbytes += 6 * I.n_egroups * 10000 * sizeof(float);
#endif
return nbytes;
}
// Calculates Time per Intersection
double time_per_intersection( Input I, double time )
{
/* This was the old estimate - new way uses actual tracking data
double tpi = time / (double) I.ntracks /
(double) I.segments_per_track / (double) I.n_egroups / 1e-9 / 2;
*/
double tpi = time / (double) I.segments_processed * 1.0e9 / (double) I.n_egroups;
return tpi;
}