double linear(dofft_closure *k, int realp, int n, C *inA, C *inB, C *inC, C *outA, C *outB, C *outC, C *tmp, int rounds, double tol) { int j; double e = 0.0; for (j = 0; j < rounds; ++j) { C alpha, beta; c_re(alpha) = mydrand(); c_im(alpha) = realp ? 0.0 : mydrand(); c_re(beta) = mydrand(); c_im(beta) = realp ? 0.0 : mydrand(); arand(inA, n); arand(inB, n); k->apply(k, inA, outA); k->apply(k, inB, outB); ascale(outA, alpha, n); ascale(outB, beta, n); aadd(tmp, outA, outB, n); ascale(inA, alpha, n); ascale(inB, beta, n); aadd(inC, inA, inB, n); k->apply(k, inC, outC); e = dmax(e, acmp(outC, tmp, n, "linear", tol)); } return e; }
/* @brief sets the neutron's direction to a random direction based on the neutron's random number seed */ void Neutron::sampleDirection() { // sample azimuthal angle double phi = 2 * M_PI * arand(); // sample cosine of the polar angle double mu = 2 * arand() - 1.0; // set diection _neutron_direction[0] = sqrt(1 - mu*mu) * cos(phi); _neutron_direction[1] = sqrt(1 - mu*mu) * sin(phi); _neutron_direction[2] = mu; }
static void get_vtx(struct asteroid *a, float r) { float theta = 360.0 / NUM_VTX; for (int i = 0; i < NUM_VTX;) { float x_var = arand() * MAX_VARIANCE * r; float y_var = arand() * MAX_VARIANCE * r; int deviation_size = NUM_VTX / 2 + rand() % (NUM_VTX / 2); deviation_size /= asteroid_smoothness; for (int j = 0; j < deviation_size && i < NUM_VTX; j++, i++) { x_var += drand() * MAX_INTM_VARIANCE * r; y_var += drand() * MAX_INTM_VARIANCE * r; float x = cos(deg_to_radf(theta * i)) * r + x_var; float y = sin(deg_to_radf(theta * i)) * r + y_var; a->vtx[i].x = x; a->vtx[i].y = y; } } }
void accuracy_test(dofft_closure *k, aconstrain constrain, int sign, int n, C *a, C *b, int rounds, int impulse_rounds, double t[6]) { int r, i; int ntests = 0; bench_complex czero = {0, 0}; for (i = 0; i < 6; ++i) t[i] = 0.0; for (r = 0; r < rounds; ++r) { arand(a, n); if (one_accuracy_test(k, constrain, sign, n, a, b, t)) ++ntests; } /* impulses at beginning of array */ for (r = 0; r < impulse_rounds; ++r) { if (r > n - r - 1) continue; caset(a, n, czero); c_re(a[r]) = c_im(a[r]) = 1.0; if (one_accuracy_test(k, constrain, sign, n, a, b, t)) ++ntests; } /* impulses at end of array */ for (r = 0; r < impulse_rounds; ++r) { if (r <= n - r - 1) continue; caset(a, n, czero); c_re(a[n - r - 1]) = c_im(a[n - r - 1]) = 1.0; if (one_accuracy_test(k, constrain, sign, n, a, b, t)) ++ntests; } /* randomly-located impulses */ for (r = 0; r < impulse_rounds; ++r) { caset(a, n, czero); i = rand() % n; c_re(a[i]) = c_im(a[i]) = 1.0; if (one_accuracy_test(k, constrain, sign, n, a, b, t)) ++ntests; } t[0] /= ntests; t[1] = sqrt(t[1] / ntests); t[3] /= ntests; t[4] = sqrt(t[4] / ntests); fftaccuracy_done(); }
double tf_shift(dofft_closure *k, int realp, const bench_tensor *sz, int n, int vecn, double sign, C *inA, C *inB, C *outA, C *outB, C *tmp, int rounds, double tol, int which_shift) { int nb, na, dim, N = n * vecn; int i, j; double e = 0.0; /* test 3: check the time-shift property */ /* the paper performs more tests, but this code should be fine too */ nb = 1; na = n; /* check shifts across all SZ dimensions */ for (dim = 0; dim < sz->rnk; ++dim) { int ncur = sz->dims[dim].n; na /= ncur; for (j = 0; j < rounds; ++j) { arand(inA, N); if (which_shift == TIME_SHIFT) { for (i = 0; i < vecn; ++i) { if (realp) mkreal(inA + i * n, n); arol(inB + i * n, inA + i * n, ncur, nb, na); } k->apply(k, inA, outA); k->apply(k, inB, outB); for (i = 0; i < vecn; ++i) aphase_shift(tmp + i * n, outB + i * n, ncur, nb, na, sign); e = dmax(e, acmp(tmp, outA, N, "time shift", tol)); } else { for (i = 0; i < vecn; ++i) { if (realp) mkhermitian(inA + i * n, sz->rnk, sz->dims, 1); aphase_shift(inB + i * n, inA + i * n, ncur, nb, na, -sign); } k->apply(k, inA, outA); k->apply(k, inB, outB); for (i = 0; i < vecn; ++i) arol(tmp + i * n, outB + i * n, ncur, nb, na); e = dmax(e, acmp(tmp, outA, N, "freq shift", tol)); } } nb *= ncur; } return e; }
/* @brief samples an initial neutron energy group after fission @param chi the neutron emission spectrum from fission @return the group number of the emitted neutron */ int Neutron::sampleNeutronEnergyGroup(std::vector <double> chi) { double r = arand(); double chi_sum = 0.0; for (int g=0; g<chi.size(); ++g) { chi_sum += chi[g]; if (r<chi_sum) { return g; } } return chi.size() - 1; }
void preserves_input(dofft_closure *k, aconstrain constrain, int n, C *inA, C *inB, C *outB, int rounds) { int j; int recopy_input = k->recopy_input; k->recopy_input = 1; for (j = 0; j < rounds; ++j) { arand(inA, n); if (constrain) constrain(inA, n); acopy(inB, inA, n); k->apply(k, inB, outB); acmp(inB, inA, n, "preserves_input", 0.0); } k->recopy_input = recopy_input; }
/* @brief samples the neutron energy group after a scattering event @param scattering_matrix the scattering cross section matrix @param group the neutron energy group before scattering @return the neutron group after scattering */ int Neutron::sampleScatteredGroup(std::vector <double> &scattering_matrix, int group) { // get the total scattering cross-section from this group int num_groups = scattering_matrix.size(); double scattering_total = 0; for (int g=0; g < num_groups; ++g) scattering_total += scattering_matrix[g]; // sample the outgoing scattered energy group double r = arand() * scattering_total; double scatter_sum = 0.0; for (int g=0; g<num_groups; ++g) { scatter_sum += scattering_matrix[g]; if (r<scatter_sum) { return g; } } // return the last group if no group has been found yet return num_groups - 1; }
static double impulse0(dofft_closure *k, int n, int vecn, C *inA, C *inB, C *inC, C *outA, C *outB, C *outC, C *tmp, int rounds, double tol) { int N = n * vecn; double e = 0.0; int j; k->apply(k, inA, tmp); e = dmax(e, acmp(tmp, outA, N, "impulse 1", tol)); for (j = 0; j < rounds; ++j) { arand(inB, N); asub(inC, inA, inB, N); k->apply(k, inB, outB); k->apply(k, inC, outC); aadd(tmp, outB, outC, N); e = dmax(e, acmp(tmp, outA, N, "impulse", tol)); } return e; }