/** * @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]); }
/** * @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; }
/** * @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); } } } }
/** * @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); } } }
/** * @brief Updates the boundary flux for a Track given boundary conditions. * @details For reflective and periodic boundary conditions, the outgoing * boundary flux for the Track is given to the corresponding reflecting * or periodic Track. For vacuum boundary conditions, the outgoing flux * is 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 transfer_flux; int track_out_id; /* For the "forward" direction */ if (direction) { start = _tracks[track_id]->isNextOut() * _polar_times_groups; transfer_flux = _tracks[track_id]->getTransferFluxOut(); track_out_id = _tracks[track_id]->getTrackOut()->getUid(); } /* For the "reverse" direction */ else { start = _tracks[track_id]->isNextIn() * _polar_times_groups; transfer_flux = _tracks[track_id]->getTransferFluxIn(); 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 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) * transfer_flux; } } }
/** * @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_source(fsr_id,e))*exponential; fsr_flux[e] += delta_psi * _polar_weights[p]; track_flux(p,e) -= delta_psi; } } if (_cmfd->getMesh()->getCmfdOn()){ if (curr_segment->_mesh_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(&_mesh_surface_locks[curr_segment->_mesh_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->_mesh_surface_fwd,e) += track_flux(p,e)*_polar_weights[p]/2.0; pe++; } } /* Release Cmfd Mesh surface mutual exclusion lock */ omp_unset_lock(&_mesh_surface_locks[curr_segment->_mesh_surface_fwd]); } else if (curr_segment->_mesh_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(&_mesh_surface_locks[curr_segment->_mesh_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->_mesh_surface_bwd,e) += track_flux(p,e)*_polar_weights[p]/2.0; pe++; } } /* Release Cmfd Mesh surface mutual exclusion lock */ omp_unset_lock(&_mesh_surface_locks[curr_segment->_mesh_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; }