• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmc-dev / openmc / 19102841639

05 Nov 2025 01:01PM UTC coverage: 82.019% (-3.1%) from 85.155%
19102841639

Pull #3252

github

web-flow
Merge 3c71decac into bd76fc056
Pull Request #3252: Adding vtkhdf option to write vtk data

16722 of 23233 branches covered (71.98%)

Branch coverage included in aggregate %.

61 of 66 new or added lines in 1 file covered. (92.42%)

3177 existing lines in 103 files now uncovered.

54247 of 63294 relevant lines covered (85.71%)

42990146.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.31
/src/random_ray/linear_source_domain.cpp
1
#include "openmc/random_ray/linear_source_domain.h"
2

3
#include "openmc/cell.h"
4
#include "openmc/geometry.h"
5
#include "openmc/material.h"
6
#include "openmc/message_passing.h"
7
#include "openmc/mgxs_interface.h"
8
#include "openmc/output.h"
9
#include "openmc/plot.h"
10
#include "openmc/random_ray/random_ray.h"
11
#include "openmc/simulation.h"
12
#include "openmc/tallies/filter.h"
13
#include "openmc/tallies/tally.h"
14
#include "openmc/tallies/tally_scoring.h"
15
#include "openmc/timer.h"
16

17
namespace openmc {
18

19
//==============================================================================
20
// LinearSourceDomain implementation
21
//==============================================================================
22

23
void LinearSourceDomain::batch_reset()
6,435✔
24
{
25
  FlatSourceDomain::batch_reset();
6,435✔
26
#pragma omp parallel for
3,510✔
27
  for (int64_t sr = 0; sr < n_source_regions(); sr++) {
13,098,190✔
28
    source_regions_.centroid_iteration(sr) = {0.0, 0.0, 0.0};
13,095,265✔
29
    source_regions_.mom_matrix(sr) = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
13,095,265✔
30
  }
31
#pragma omp parallel for
3,510✔
32
  for (int64_t se = 0; se < n_source_elements(); se++) {
15,043,990✔
33
    source_regions_.flux_moments_new(se) = {0.0, 0.0, 0.0};
15,041,065✔
34
  }
35
}
6,435✔
36

37
void LinearSourceDomain::update_single_neutron_source(SourceRegionHandle& srh)
29,630,117✔
38
{
39
  // Reset all source regions to zero (important for void regions)
40
  for (int g = 0; g < negroups_; g++) {
63,605,674✔
41
    srh.source(g) = 0.0;
33,975,557✔
42
  }
43

44
  // Add scattering + fission source
45
  int material = srh.material();
29,630,117✔
46
  if (material != MATERIAL_VOID) {
29,630,117✔
47
    double inverse_k_eff = 1.0 / k_eff_;
29,190,117✔
48
    MomentMatrix invM = srh.mom_matrix().inverse();
29,190,117✔
49

50
    for (int g_out = 0; g_out < negroups_; g_out++) {
62,725,674✔
51
      double sigma_t = sigma_t_[material * negroups_ + g_out];
33,535,557✔
52

53
      double scatter_flat = 0.0f;
33,535,557✔
54
      double fission_flat = 0.0f;
33,535,557✔
55
      MomentArray scatter_linear = {0.0, 0.0, 0.0};
33,535,557✔
56
      MomentArray fission_linear = {0.0, 0.0, 0.0};
33,535,557✔
57

58
      for (int g_in = 0; g_in < negroups_; g_in++) {
108,945,474✔
59
        // Handles for the flat and linear components of the flux
60
        double flux_flat = srh.scalar_flux_old(g_in);
75,409,917✔
61
        MomentArray flux_linear = srh.flux_moments_old(g_in);
75,409,917✔
62

63
        // Handles for cross sections
64
        double sigma_s =
65
          sigma_s_[material * negroups_ * negroups_ + g_out * negroups_ + g_in];
75,409,917✔
66
        double nu_sigma_f = nu_sigma_f_[material * negroups_ + g_in];
75,409,917✔
67
        double chi = chi_[material * negroups_ + g_out];
75,409,917✔
68

69
        // Compute source terms for flat and linear components of the flux
70
        scatter_flat += sigma_s * flux_flat;
75,409,917✔
71
        fission_flat += nu_sigma_f * flux_flat * chi;
75,409,917✔
72
        scatter_linear += sigma_s * flux_linear;
75,409,917✔
73
        fission_linear += nu_sigma_f * flux_linear * chi;
75,409,917✔
74
      }
75

76
      // Compute the flat source term
77
      srh.source(g_out) =
67,071,114✔
78
        (scatter_flat + fission_flat * inverse_k_eff) / sigma_t;
33,535,557✔
79

80
      // Compute the linear source terms. In the first 10 iterations when the
81
      // centroids and spatial moments are not well known, we will leave the
82
      // source gradients as zero so as to avoid causing any numerical
83
      // instability. If a negative source is encountered, this region must be
84
      // very small/noisy or have poorly developed spatial moments, so we zero
85
      // the source gradients (effectively making this a flat source region
86
      // temporarily), so as to improve stability.
87
      if (simulation::current_batch > 10 && srh.source(g_out) >= 0.0) {
33,535,557✔
88
        srh.source_gradients(g_out) =
20,559,022✔
89
          invM * ((scatter_linear + fission_linear * inverse_k_eff) / sigma_t);
41,118,044✔
90
      } else {
91
        srh.source_gradients(g_out) = {0.0, 0.0, 0.0};
12,976,535✔
92
      }
93
    }
94
  }
95

96
  // Add external source if in fixed source mode
97
  if (settings::run_mode == RunMode::FIXED_SOURCE) {
29,630,117✔
98
    for (int g = 0; g < negroups_; g++) {
61,688,594✔
99
      srh.source(g) += srh.external_source(g);
32,279,797✔
100
    }
101
  }
102
}
29,630,117✔
103

104
void LinearSourceDomain::normalize_scalar_flux_and_volumes(
6,435✔
105
  double total_active_distance_per_iteration)
106
{
107
  double normalization_factor = 1.0 / total_active_distance_per_iteration;
6,435✔
108
  double volume_normalization_factor =
6,435✔
109
    1.0 / (total_active_distance_per_iteration * simulation::current_batch);
6,435✔
110

111
// Normalize flux to total distance travelled by all rays this iteration
112
#pragma omp parallel for
3,510✔
113
  for (int64_t se = 0; se < n_source_elements(); se++) {
15,431,290✔
114
    source_regions_.scalar_flux_new(se) *= normalization_factor;
15,428,365✔
115
    source_regions_.flux_moments_new(se) *= normalization_factor;
15,428,365✔
116
  }
117

118
// Accumulate cell-wise ray length tallies collected this iteration, then
119
// update the simulation-averaged cell-wise volume estimates
120
#pragma omp parallel for
3,510✔
121
  for (int64_t sr = 0; sr < n_source_regions(); sr++) {
13,456,090✔
122
    source_regions_.centroid_t(sr) += source_regions_.centroid_iteration(sr);
13,453,165✔
123
    source_regions_.mom_matrix_t(sr) += source_regions_.mom_matrix(sr);
13,453,165✔
124
    source_regions_.volume_t(sr) += source_regions_.volume(sr);
13,453,165✔
125
    source_regions_.volume_sq_t(sr) += source_regions_.volume_sq(sr);
13,453,165✔
126
    source_regions_.volume_naive(sr) =
26,906,330✔
127
      source_regions_.volume(sr) * normalization_factor;
13,453,165✔
128
    source_regions_.volume(sr) =
26,906,330✔
129
      source_regions_.volume_t(sr) * volume_normalization_factor;
13,453,165✔
130
    source_regions_.volume_sq(sr) =
26,906,330✔
131
      source_regions_.volume_sq_t(sr) / source_regions_.volume_t(sr);
13,453,165✔
132
    if (source_regions_.volume_t(sr) > 0.0) {
13,453,165✔
133
      double inv_volume = 1.0 / source_regions_.volume_t(sr);
13,453,160✔
134
      source_regions_.centroid(sr) = source_regions_.centroid_t(sr);
13,453,160✔
135
      source_regions_.centroid(sr) *= inv_volume;
13,453,160✔
136
      source_regions_.mom_matrix(sr) = source_regions_.mom_matrix_t(sr);
13,453,160✔
137
      source_regions_.mom_matrix(sr) *= inv_volume;
13,453,160✔
138
    }
139
  }
140
}
6,435✔
141

142
void LinearSourceDomain::set_flux_to_flux_plus_source(
31,047,709✔
143
  int64_t sr, double volume, int g)
144
{
145
  int material = source_regions_.material(sr);
31,047,709✔
146
  if (material == MATERIAL_VOID) {
31,047,709✔
147
    FlatSourceDomain::set_flux_to_flux_plus_source(sr, volume, g);
440,000✔
148
  } else {
149
    source_regions_.scalar_flux_new(sr, g) /= volume;
30,607,709✔
150
    source_regions_.scalar_flux_new(sr, g) += source_regions_.source(sr, g);
30,607,709✔
151
  }
152
  // If a source region is small, then the moments are likely noisy, so we zero
153
  // them. This is reasonable, given that small regions can get by with a flat
154
  // source approximation anyhow.
155
  if (source_regions_.is_small(sr)) {
31,047,709✔
156
    source_regions_.flux_moments_new(sr, g) = {0.0, 0.0, 0.0};
3,158,254✔
157
  } else {
158
    source_regions_.flux_moments_new(sr, g) *= (1.0 / volume);
27,889,455✔
159
  }
160
}
31,047,709✔
161

162
void LinearSourceDomain::set_flux_to_old_flux(int64_t sr, int g)
1,364✔
163
{
164
  source_regions_.scalar_flux_new(sr, g) =
2,728✔
165
    source_regions_.scalar_flux_old(sr, g);
1,364✔
166
  source_regions_.flux_moments_new(sr, g) =
2,728✔
167
    source_regions_.flux_moments_old(sr, g);
1,364✔
168
}
1,364✔
169

170
void LinearSourceDomain::accumulate_iteration_flux()
2,640✔
171
{
172
  // Accumulate scalar flux
173
  FlatSourceDomain::accumulate_iteration_flux();
2,640✔
174

175
  // Accumulate scalar flux moments
176
#pragma omp parallel for
1,440✔
177
  for (int64_t se = 0; se < n_source_elements(); se++) {
6,577,100✔
178
    source_regions_.flux_moments_t(se) += source_regions_.flux_moments_new(se);
6,575,900✔
179
  }
180
}
2,640✔
181

UNCOV
182
double LinearSourceDomain::evaluate_flux_at_point(
×
183
  Position r, int64_t sr, int g) const
184
{
UNCOV
185
  double phi_flat = FlatSourceDomain::evaluate_flux_at_point(r, sr, g);
×
186

UNCOV
187
  Position local_r = r - source_regions_.centroid(sr);
×
UNCOV
188
  MomentArray phi_linear = source_regions_.flux_moments_t(sr, g);
×
UNCOV
189
  phi_linear *= 1.0 / (settings::n_batches - settings::n_inactive);
×
190

UNCOV
191
  MomentMatrix invM = source_regions_.mom_matrix(sr).inverse();
×
UNCOV
192
  MomentArray phi_solved = invM * phi_linear;
×
193

UNCOV
194
  return phi_flat + phi_solved.dot(local_r);
×
195
}
196

197
} // namespace openmc
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc