Пример #1
0
/**
 * @brief Computes the contribution to the FSR scalar flux from a segment.
 * @details This method integrates the angular flux for a Track segment across
 *        energy groups and polar angles, and tallies it into the FSR scalar
 *        flux, and updates the Track's angular flux.
 * @param curr_segment a pointer to the Track segment of interest
 * @param azim_index a pointer to the azimuthal angle index for this segment
 * @param track_flux a pointer to the Track's angular flux
 * @param fsr_flux a pointer to the temporary FSR flux buffer
 */
void VectorizedSolver::tallyScalarFlux(segment* curr_segment,
                                       int azim_index,
                                       FP_PRECISION* track_flux,
                                       FP_PRECISION* fsr_flux) {

  int tid = omp_get_thread_num();
  int fsr_id = curr_segment->_region_id;
  FP_PRECISION* delta_psi = &_delta_psi[tid*_num_groups];
  FP_PRECISION* exponentials = &_thread_exponentials[tid*_polar_times_groups];

  computeExponentials(curr_segment, exponentials);

  /* Set the FSR scalar flux buffer to zero */
  memset(fsr_flux, 0.0, _num_groups * sizeof(FP_PRECISION));

  /* Tally the flux contribution from segment to FSR's scalar flux */
  /* Loop over polar angles */
  for (int p=0; p < _num_polar; p++) {

    /* Loop over each energy group vector length */
    for (int v=0; v < _num_vector_lengths; v++) {

      /* Loop over energy groups within this vector */
#pragma simd vectorlength(VEC_LENGTH)
      for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++)
        delta_psi[e] = track_flux(p,e) - _reduced_sources(fsr_id,e);

      /* Loop over energy groups within this vector */
#pragma simd vectorlength(VEC_LENGTH)
      for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++)
        delta_psi[e] *= exponentials(p,e);

      /* Loop over energy groups within this vector */
#pragma simd vectorlength(VEC_LENGTH)
      for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++)
        fsr_flux[e] += delta_psi[e] * _polar_weights(azim_index,p);

      /* Loop over energy groups within this vector */
#pragma simd vectorlength(VEC_LENGTH)
      for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++)
        track_flux(p,e) -= delta_psi[e];
    }
  }

  /* Atomically increment the FSR scalar flux from the temporary array */
  omp_set_lock(&_FSR_locks[fsr_id]);
  {
#ifdef SINGLE
    vsAdd(_num_groups, &_scalar_flux(fsr_id,0), fsr_flux,
          &_scalar_flux(fsr_id,0));
#else
    vdAdd(_num_groups, &_scalar_flux(fsr_id,0), fsr_flux,
          &_scalar_flux(fsr_id,0));
#endif
  }
  omp_unset_lock(&_FSR_locks[fsr_id]);
}
Пример #2
0
/**
 * @brief Computes the contribution to the FSR scalar flux from a Track segment.
 * @details This method integrates the angular flux for a Track segment across
 *        energy groups and polar angles, and tallies it into the FSR scalar
 *        flux, and updates the Track's angular flux.
 * @param curr_segment a pointer to the Track segment of interest
 * @param azim_index a pointer to the azimuthal angle index for this segment
 * @param track_flux a pointer to the Track's angular flux
 * @param fsr_flux a pointer to the temporary FSR flux buffer
 * @param fwd
 */
void VectorizedSolver::scalarFluxTally(segment* curr_segment,
                                       int azim_index,
                                       FP_PRECISION* track_flux,
                                       FP_PRECISION* fsr_flux,
                                       bool fwd){

  int tid = omp_get_thread_num();
  int fsr_id = curr_segment->_region_id;
  FP_PRECISION length = curr_segment->_length;
  FP_PRECISION* sigma_t = curr_segment->_material->getSigmaT();

  /* The change in angular flux along this Track segment in the FSR */
  FP_PRECISION delta_psi;
  FP_PRECISION* exponentials = &_thread_exponentials[tid*_polar_times_groups];

  computeExponentials(curr_segment, exponentials);

  /* Set the FSR scalar flux buffer to zero */
  memset(fsr_flux, 0.0, _num_groups * sizeof(FP_PRECISION));

  /* Tally the flux contribution from segment to FSR's scalar flux */
  /* Loop over polar angles */
  for (int p=0; p < _num_polar; p++){

    /* Loop over each energy group vector length */
    for (int v=0; v < _num_vector_lengths; v++) {

      /* Loop over energy groups within this vector */
      #pragma simd vectorlength(VEC_LENGTH) private(delta_psi)
      for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) {
        delta_psi = (track_flux(p,e) - _reduced_source(fsr_id,e)) *
                   exponentials(p,e);
        fsr_flux[e] += delta_psi * _polar_weights(azim_index,p);
        track_flux(p,e) -= delta_psi;
      }
    }
  }

  /* Atomically increment the FSR scalar flux from the temporary array */
  omp_set_lock(&_FSR_locks[fsr_id]);
  {
    #ifdef SINGLE
    vsAdd(_num_groups, &_scalar_flux(fsr_id,0), fsr_flux,
          &_scalar_flux(fsr_id,0));
    #else
    vdAdd(_num_groups, &_scalar_flux(fsr_id,0), fsr_flux,
          &_scalar_flux(fsr_id,0));
    #endif
  }
  omp_unset_lock(&_FSR_locks[fsr_id]);

  return;
}
Пример #3
0
/**
 * @brief Builds a linear interpolation table to compute exponentials for
 *        each segment of each Track for each polar angle.
 */
void CPUSolver::buildExpInterpTable() {

  log_printf(INFO, "Building exponential interpolation table...");

  FP_PRECISION azim_weight;

  _polar_weights = new FP_PRECISION[_num_azim*_num_polar];

  /* Compute the total azimuthal weight for tracks at each polar angle */
  #pragma omp parallel for private(azim_weight) schedule(guided)
  for (int i=0; i < _num_azim; i++) {

    azim_weight = _azim_weights[i];

    for (int p=0; p < _num_polar; p++)
      _polar_weights(i,p) = azim_weight*_quad->getMultiple(p)*FOUR_PI;
  }

  /* Set size of interpolation table */
  int num_array_values = 10 * sqrt(1./(8.*_source_convergence_thresh*1e-2));
  _exp_table_spacing = 10. / num_array_values;
  _exp_table_size = _two_times_num_polar * num_array_values;
  _exp_table_max_index = _exp_table_size - _two_times_num_polar - 1.;

  log_printf(DEBUG, "Exponential interpolation table size: %i, max index: %i",
             _exp_table_size, _exp_table_max_index);

  /* Allocate array for the table */
  _exp_table = new FP_PRECISION[_exp_table_size];

  FP_PRECISION expon;
  FP_PRECISION intercept;
  FP_PRECISION slope;

  /* Create exponential linear interpolation table */
  for (int i=0; i < num_array_values; i ++){
    for (int p=0; p < _num_polar; p++){
      expon = exp(- (i * _exp_table_spacing) / _quad->getSinTheta(p));
      slope = - expon / _quad->getSinTheta(p);
      intercept = expon * (1 + (i * _exp_table_spacing)/_quad->getSinTheta(p));
      _exp_table[_two_times_num_polar * i + 2 * p] = slope;
      _exp_table[_two_times_num_polar * i + 2 * p + 1] = intercept;
    }
  }

  /* Compute the reciprocal of the table entry spacing */
  _inverse_exp_table_spacing = 1.0 / _exp_table_spacing;

  return;
}
Пример #4
0
/**
 * @brief Updates the boundary flux for a Track given boundary conditions.
 * @details For reflective boundary conditions, the outgoing boundary flux
 *          for the Track is given to the reflecting Track. For vacuum
 *          boundary conditions, the outgoing flux tallied as leakage.
 * @param track_id the ID number for the Track of interest
 * @param azim_index a pointer to the azimuthal angle index for this segment
 * @param direction the Track direction (forward - true, reverse - false)
 * @param track_flux a pointer to the Track's outgoing angular flux
 */
void VectorizedSolver::transferBoundaryFlux(int track_id, int azim_index,
                                            bool direction,
                                            FP_PRECISION* track_flux) {
  int start;
  bool bc;
  FP_PRECISION* track_leakage;
  int track_out_id;

  /* Extract boundary conditions for this Track and the pointer to the
   * outgoing reflective Track, and index into the leakage array */

  /* For the "forward" direction */
  if (direction) {
    start = _tracks[track_id]->isReflOut() * _polar_times_groups;
    track_leakage = &_boundary_leakage(track_id,0);
    track_out_id = _tracks[track_id]->getTrackOut()->getUid();
    bc = _tracks[track_id]->getBCOut();
  }

  /* For the "reverse" direction */
  else {
    start = _tracks[track_id]->isReflIn() * _polar_times_groups;
    track_leakage = &_boundary_leakage(track_id,_polar_times_groups);
    track_out_id = _tracks[track_id]->getTrackIn()->getUid();
    bc = _tracks[track_id]->getBCIn();
  }

  FP_PRECISION* track_out_flux = &_boundary_flux(track_out_id,0,0,start);

  /* Loop over polar angles and energy groups */
  for (int p=0; p < _num_polar; p++) {

    /* Loop over each energy group vector length */
    for (int v=0; v < _num_vector_lengths; v++) {

      /* Loop over energy groups within this vector */
      #pragma simd vectorlength(VEC_LENGTH)
      for (int e=v*VEC_LENGTH; e < (v+1)*VEC_LENGTH; e++) {
        track_out_flux(p,e) = track_flux(p,e) * bc;
        track_leakage(p,e) = track_flux(p,e) *
                             _polar_weights(azim_index,p) * (!bc);
      }
    }
  }
}
Пример #5
0
/**
 * @brief Updates the boundary flux for a Track given boundary conditions.
 * @details For reflective boundary conditions, the outgoing boundary flux
 *          for the Track is given to the reflecting Track. For vacuum
 *          boundary conditions, the outgoing flux tallied as leakage.
 * @param track_id the ID number for the Track of interest
 * @param azim_index a pointer to the azimuthal angle index for this segment
 * @param direction the Track direction (forward - true, reverse - false)
 * @param track_flux a pointer to the Track's outgoing angular flux
 */
void CPUSolver::transferBoundaryFlux(int track_id,
                                     int azim_index,
                                     bool direction,
                                     FP_PRECISION* track_flux) {
  int start;
  int bc;
  FP_PRECISION* track_leakage;
  int track_out_id;

  /* Extract boundary conditions for this Track and the pointer to the
   * outgoing reflective Track, and index into the leakage array */

  /* For the "forward" direction */
  if (direction) {
    start = _tracks[track_id]->isReflOut() * _polar_times_groups;
    bc = (int)_tracks[track_id]->getBCOut();
    track_leakage = &_boundary_leakage(track_id,0);
    track_out_id = _tracks[track_id]->getTrackOut()->getUid();
  }

  /* For the "reverse" direction */
  else {
    start = _tracks[track_id]->isReflIn() * _polar_times_groups;
    bc = (int)_tracks[track_id]->getBCIn();
    track_leakage = &_boundary_leakage(track_id,_polar_times_groups);
    track_out_id = _tracks[track_id]->getTrackIn()->getUid();
  }

  FP_PRECISION* track_out_flux = &_boundary_flux(track_out_id,0,0,start);

  /* Loop over polar angles and energy groups */
  for (int e=0; e < _num_groups; e++) {
    for (int p=0; p < _num_polar; p++) {
      track_out_flux(p,e) = track_flux(p,e) * bc;
      track_leakage(p,e) = track_flux(p,e) *
                            _polar_weights(azim_index,p) * (!bc);
    }
  }
}
Пример #6
0
/**
 * @brief Computes the contribution to the FSR scalar flux from a Track segment.
 * @details This method integrates the angular flux for a Track segment across
 *          energy groups and polar angles, and tallies it into the FSR
 *          scalar flux, and updates the Track's angular flux.
 * @param curr_segment a pointer to the Track segment of interest
 * @param azim_index a pointer to the azimuthal angle index for this segment
 * @param track_flux a pointer to the Track's angular flux
 * @param fsr_flux a pointer to the temporary FSR flux buffer
 * @param fwd
 */
void CPUSolver::scalarFluxTally(segment* curr_segment,
                                int azim_index,
                                FP_PRECISION* track_flux,
                                FP_PRECISION* fsr_flux,
                                bool fwd){

  int tid = omp_get_thread_num();
  int fsr_id = curr_segment->_region_id;
  FP_PRECISION length = curr_segment->_length;
  FP_PRECISION* sigma_t = curr_segment->_material->getSigmaT();

  /* The change in angular flux along this Track segment in the FSR */
  FP_PRECISION delta_psi;
  FP_PRECISION exponential;

  /* Set the FSR scalar flux buffer to zero */
  memset(fsr_flux, 0.0, _num_groups * sizeof(FP_PRECISION));

  /* Loop over energy groups */
  for (int e=0; e < _num_groups; e++) {

    /* Loop over polar angles */
    for (int p=0; p < _num_polar; p++){
      exponential = computeExponential(sigma_t[e], length, p);
      delta_psi = (track_flux(p,e)-_reduced_sources(fsr_id,e))*exponential;
      fsr_flux[e] += delta_psi * _polar_weights(azim_index,p);
      track_flux(p,e) -= delta_psi;
    }
  }

  if (_cmfd != NULL && _cmfd->isFluxUpdateOn()){
    if (curr_segment->_cmfd_surface_fwd != -1 && fwd){

      int pe = 0;

      /* Atomically increment the Cmfd Mesh surface current from the
       * temporary array using mutual exclusion locks */
      omp_set_lock(&_cmfd_surface_locks[curr_segment->_cmfd_surface_fwd]);

      /* Loop over energy groups */
      for (int e = 0; e < _num_groups; e++) {

        /* Loop over polar angles */
        for (int p = 0; p < _num_polar; p++){

          /* Increment current (polar and azimuthal weighted flux, group) */
          _surface_currents(curr_segment->_cmfd_surface_fwd,e) +=
              track_flux(p,e)*_polar_weights(azim_index,p)/2.0;
          pe++;
        }
      }

      /* Release Cmfd Mesh surface mutual exclusion lock */
      omp_unset_lock(&_cmfd_surface_locks[curr_segment->_cmfd_surface_fwd]);

    }
    else if (curr_segment->_cmfd_surface_bwd != -1 && !fwd){

      int pe = 0;

      /* Atomically increment the Cmfd Mesh surface current from the
       * temporary array using mutual exclusion locks */
      omp_set_lock(&_cmfd_surface_locks[curr_segment->_cmfd_surface_bwd]);

      /* Loop over energy groups */
      for (int e = 0; e < _num_groups; e++) {

        /* Loop over polar angles */
        for (int p = 0; p < _num_polar; p++){

          /* Increment current (polar and azimuthal weighted flux, group) */
          _surface_currents(curr_segment->_cmfd_surface_bwd,e) +=
              track_flux(p,e)*_polar_weights(azim_index,p)/2.0;
          pe++;
        }
      }

      /* Release Cmfd Mesh surface mutual exclusion lock */
      omp_unset_lock(&_cmfd_surface_locks[curr_segment->_cmfd_surface_bwd]);
    }
  }

  /* Atomically increment the FSR scalar flux from the temporary array */
  omp_set_lock(&_FSR_locks[fsr_id]);
  {
    for (int e=0; e < _num_groups; e++)
      _scalar_flux(fsr_id,e) += fsr_flux[e];
  }
  omp_unset_lock(&_FSR_locks[fsr_id]);

  return;
}
Пример #7
0
/**
 * @brief Builds a linear interpolation table to compute exponentials for
 *        each segment of each Track for each polar angle.
 */
void CPUSolver::buildExpInterpTable() {

  log_printf(INFO, "Building exponential interpolation table...");

  FP_PRECISION azim_weight;

  if (_polar_weights != NULL)
    delete [] _polar_weights;

  _polar_weights = new FP_PRECISION[_num_azim*_num_polar];

  /* Compute the total azimuthal weight for tracks at each polar angle */
  #pragma omp parallel for private(azim_weight) schedule(guided)
  for (int i=0; i < _num_azim; i++) {

    azim_weight = _azim_weights[i];

    for (int p=0; p < _num_polar; p++)
      _polar_weights(i,p) = azim_weight*_quad->getMultiple(p)*FOUR_PI;
  }

  /* Find largest optical path length track segment */
  FP_PRECISION tau = _track_generator->getMaxOpticalLength();

  /* Expand tau slightly to accomodate track segments which have a
   * length very nearly equal to the maximum value */
  tau *= 1.01;

  /* Set size of interpolation table */
  int num_array_values = tau * sqrt(1./(8.*_source_convergence_thresh*1e-2));
  _exp_table_spacing = tau / num_array_values;
  _exp_table_size = _two_times_num_polar * num_array_values;
  _exp_table_max_index = _exp_table_size - _two_times_num_polar - 1.;

  log_printf(DEBUG, "Exponential interpolation table size: %i, max index: %i",
             _exp_table_size, _exp_table_max_index);

  /* Allocate array for the table */
  if (_exp_table != NULL)
    delete [] _exp_table;

  _exp_table = new FP_PRECISION[_exp_table_size];

  FP_PRECISION expon;
  FP_PRECISION intercept;
  FP_PRECISION slope;

  /* Create exponential linear interpolation table */
  for (int i=0; i < num_array_values; i ++){
    for (int p=0; p < _num_polar; p++){
      expon = exp(- (i * _exp_table_spacing) / _quad->getSinTheta(p));
      slope = - expon / _quad->getSinTheta(p);
      intercept = expon * (1 + (i * _exp_table_spacing)/_quad->getSinTheta(p));
      _exp_table[_two_times_num_polar * i + 2 * p] = slope;
      _exp_table[_two_times_num_polar * i + 2 * p + 1] = intercept;
    }
  }

  /* Compute the reciprocal of the table entry spacing */
  _inverse_exp_table_spacing = 1.0 / _exp_table_spacing;

  return;
}