openmc icon indicating copy to clipboard operation
openmc copied to clipboard

Calculation of micro-cross section in void for nuclides specified on tally

Open teade opened this issue 8 months ago • 0 comments

Description

It is useful to be able to calculate the micro-cross section of nuclides even if the particle is travelling through void. The ability to calculate the micro-cross section if the nuclide is not present in the material has been added in pull request #2539. However, this only applies if the material is not void as there is an if statement (if (p.material() != MATERIAL_VOID) ) in this section of the code: https://github.com/openmc-dev/openmc/blob/a7d1ceba3f9fe5e394a49cdf10b724094f39af11/src/tallies/tally_scoring.cpp#L2407C1-L2445C6

If this section of code could be refactored to something like:

      // Loop over nuclide bins.
      for (auto i = 0; i < tally.nuclides_.size(); ++i) {
        auto i_nuclide = tally.nuclides_[i];

        double atom_density = 0.;
        if (i_nuclide >= 0) {
          if (p.material() != MATERIAL_VOID) {
            const auto& mat = model::materials[p.material()];
            auto j = mat->mat_nuclide_index_[i_nuclide];
            if (j == C_NONE) {
              // Determine log union grid index
              if (i_log_union == C_NONE) {
                int neutron = static_cast<int>(ParticleType::neutron);
                i_log_union = std::log(p.E() / data::energy_min[neutron]) /
                              simulation::log_spacing;
              }

              // Update micro xs cache
              if (!tally.multiply_density()) {
                p.update_neutron_xs(i_nuclide, i_log_union);
                atom_density = 1.0;
              }
            } else {
              atom_density =
                tally.multiply_density() ? mat->atom_density_(j) : 1.0;
            }

          // If the particle is in void
          } else {

            if (i_log_union == C_NONE) {
              int neutron = static_cast<int>(ParticleType::neutron);
              i_log_union = std::log(p.E() / data::energy_min[neutron]) /
                            simulation::log_spacing;
            }

            // Update micro xs cache
            if (!tally.multiply_density()) {
              p.update_neutron_xs(i_nuclide, i_log_union);
              atom_density = 1.0;
            }

          }
        }

        // TODO: consider replacing this "if" with pointers or templates
        if (settings::run_CE) {
          score_general_ce_nonanalog(p, i_tally, i * tally.scores_.size(),
            filter_index, filter_weight, i_nuclide, atom_density, flux);
        } else {
          score_general_mg(p, i_tally, i * tally.scores_.size(), filter_index,
            filter_weight, i_nuclide, atom_density, flux);
        }
      }

It would allow for reaction rates and nuclear heating for a super-imposed material to be estimated, even in void.

Compatibility

This change should be compatible with existing code although it will change the functionality of tallies when nuclides are specified as values will now be created in void regions as well as those containing materials. Alternatively a new input variable could be added to the tally to allow the user to specify whether or not to include calculation of micro-cross sections in void regions.

teade avatar May 19 '25 11:05 teade