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

NREL / SolTrace / 21046664913

15 Jan 2026 09:17PM UTC coverage: 87.999% (+0.2%) from 87.815%
21046664913

Pull #96

github

web-flow
Merge a5971e7da into e78d2bfb0
Pull Request #96: 95 implement embree runner

605 of 797 new or added lines in 17 files covered. (75.91%)

14 existing lines in 7 files now uncovered.

6255 of 7108 relevant lines covered (88.0%)

7221404.67 hits per line

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

95.0
/coretrace/simulation_runner/native_runner/trace.cpp
1

2
/*******************************************************************************************************
3
 *  Copyright 2018 Alliance for Sustainable Energy, LLC
4
 *
5
 *  NOTICE: This software was developed at least in part by Alliance for Sustainable Energy, LLC
6
 *  ("Alliance") under Contract No. DE-AC36-08GO28308 with the U.S. Department of Energy and the U.S.
7
 *  The Government retains for itself and others acting on its behalf a nonexclusive, paid-up,
8
 *  irrevocable worldwide license in the software to reproduce, prepare derivative works, distribute
9
 *  copies to the public, perform publicly and display publicly, and to permit others to do so.
10
 *
11
 *  Redistribution and use in source and binary forms, with or without modification, are permitted
12
 *  provided that the following conditions are met:
13
 *
14
 *  1. Redistributions of source code must retain the above copyright notice, the above government
15
 *  rights notice, this list of conditions and the following disclaimer.
16
 *
17
 *  2. Redistributions in binary form must reproduce the above copyright notice, the above government
18
 *  rights notice, this list of conditions and the following disclaimer in the documentation and/or
19
 *  other materials provided with the distribution.
20
 *
21
 *  3. The entire corresponding source code of any redistribution, with or without modification, by a
22
 *  research entity, including but not limited to any contracting manager/operator of a United States
23
 *  National Laboratory, any institution of higher learning, and any non-profit organization, must be
24
 *  made publicly available under this license for as long as the redistribution is made available by
25
 *  the research entity.
26
 *
27
 *  4. Redistribution of this software, without modification, must refer to the software by the same
28
 *  designation. Redistribution of a modified version of this software (i) may not refer to the modified
29
 *  version by the same designation, or by any confusingly similar designation, and (ii) must refer to
30
 *  the underlying software originally provided by Alliance as "SolTrace". Except to comply with the
31
 *  foregoing, the term "SolTrace", or any confusingly similar designation may not be used to refer to
32
 *  any modified version of this software or any modified version of the underlying software originally
33
 *  provided by Alliance without the prior written consent of Alliance.
34
 *
35
 *  5. The name of the copyright holder, contributors, the United States Government, the United States
36
 *  Department of Energy, or any of their employees may not be used to endorse or promote products
37
 *  derived from this software without specific prior written permission.
38
 *
39
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
40
 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41
 *  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER,
42
 *  CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR
43
 *  EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44
 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
46
 *  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
47
 *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48
 *******************************************************************************************************/
49

50
#include "trace.hpp"
51

52
// Standard library headers
53
#include <algorithm>
54
#include <cmath>
55
#include <limits>
56
#include <sstream>
57
#include <vector>
58

59
// SimulationData headers
60
#include <constants.hpp>
61
#include <matvec.hpp>
62
#include <simulation_data_export.hpp>
63

64
// SimulationRunner header
65
#include <simulation_runner.hpp>
66

67
// NativeRunner headers
68
#include "determine_interaction_type.hpp"
69
#include "find_element_hit.hpp"
70
#include "generate_ray.hpp"
71
#include "native_runner_types.hpp"
72
#include "process_interaction.hpp"
73
#include "pt_optimizations.hpp"
74
#include "sun_to_primary_stage.hpp"
75
#include "thread_manager.hpp"
76
#include "trace_logger.hpp"
77
#include "treemesh.hpp"
78

79
namespace SolTrace::NativeRunner
80
{
81

82
        using SolTrace::Result::RayEvent;
83
        using SolTrace::Runner::RunnerStatus;
84

85
        // Trace method
86
        RunnerStatus trace_native(
25✔
87
                thread_manager_ptr manager,
88
                trace_logger_ptr logger,
89
                TSystem *System,
90
                const std::vector<unsigned int> &seeds,
91
                unsigned nthreads,
92
                uint_fast64_t NumberOfRays,
93
                uint_fast64_t MaxNumberOfRays,
94
                bool IncludeSunShape,
95
                bool IncludeErrors,
96
                bool AsPowerTower)
97
        {
98
                // Initialize Sun
99
                Vector3d PosSunStage;
25✔
100
                if (!SunToPrimaryStage(logger,
25✔
101
                                                           System,
102
                                                           System->StageList[0].get(),
25✔
103
                                                           &System->Sun,
104
                                                           PosSunStage.data))
105
                        return RunnerStatus::ERROR;
×
106

107
                // Determine if PT optimizations should be applied
108
                bool PT_override = false;
25✔
109
                if (System->StageList.size() > 0 &&
57✔
110
                        (System->StageList[0]->ElementList.size() < 10 || System->StageList.size() == 1))
32✔
111
                {
112
                        PT_override = true;
20✔
113
                }
114

115
                // Calculate hash tree for reflection to receiver plane(polar coordinates).
116
                st_hash_tree sun_hash;
25✔
117
                st_hash_tree rec_hash;
25✔
118
                // double reccm_helio[3]; // receiver centroid in heliostat field coordinates
119
                Vector3d reccm_helio;
25✔
120
                if (!PT_override)
25✔
121
                {
122
                        SetupPTOptimizations(System, AsPowerTower, sun_hash,
5✔
123
                                                                 rec_hash, reccm_helio.data);
124
                }
125

126
                // Bundle many args into a struct because the compiler was
127
                // having trouble with all the arguments...
128
                ThreadInfo my_info;
25✔
129
                my_info.manager = manager;
25✔
130
                my_info.logger = logger;
25✔
131
                my_info.System = System;
25✔
132
                // my_info.NumberOfRays = NumberOfRays / nthreads;
133
                uint_fast64_t rem = NumberOfRays % nthreads;
25✔
134
                uint_fast64_t nrays_per_thread = NumberOfRays / nthreads;
25✔
135

136
                my_info.MaxNumberOfRays = MaxNumberOfRays / nthreads + 1;
25✔
137
                my_info.IncludeSunShape = IncludeSunShape;
25✔
138
                my_info.IncludeErrors = IncludeErrors;
25✔
139
                my_info.AsPowerTower = AsPowerTower;
25✔
140
                my_info.PosSunStage = PosSunStage;
25✔
141
                my_info.sun_hash = &sun_hash;
25✔
142
                my_info.rec_hash = &rec_hash;
25✔
143
                my_info.reccm_helio = reccm_helio;
25✔
144

145
                System->RayData.SetUp(nthreads, NumberOfRays);
25✔
146
                System->SunRayCount = 0;
25✔
147

148
                for (unsigned int k = 0; k < nthreads; ++k)
50✔
149
                {
150
                        my_info.NumberOfRays = (k < rem
50✔
151
                                                                                ? nrays_per_thread + 1
25✔
152
                                                                                : nrays_per_thread);
153

154
                        ThreadManager::future my_future = std::async(
155
                                std::launch::async,
156
                                trace_single_compact,
157
                                k,
158
                                seeds[k],
25✔
159
                                my_info);
25✔
160

161
                        manager->manage(k, std::move(my_future));
25✔
162
                }
25✔
163

164
                return manager->monitor_until_completion();
25✔
165
        }
25✔
166

167
        RunnerStatus trace_single_thread(
25✔
168
                unsigned thread_id,
169
                thread_manager_ptr manager,
170
                trace_logger_ptr logger,
171
                TSystem *System,
172
                unsigned int seed,
173
                uint_fast64_t NumberOfRays,
174
                uint_fast64_t MaxNumberOfRays,
175
                bool IncludeSunShape,
176
                bool IncludeErrors,
177
                bool AsPowerTower,
178
                const Vector3d &PosSunStage,
179
                st_hash_tree *sun_hash,
180
                st_hash_tree *rec_hash,
181
                const Vector3d &reccm_helio)
182
        {
183
                // Initialize variables
184
                MTRand myrng(seed);
25✔
185

186
                // std::stringstream ss;
187
                // ss << "Thread " << thread_id
188
                //    << " tracing " << NumberOfRays << " rays"
189
                //    << std::endl;
190
                // std::cout << ss.str();
191

192
                // Determine if PT optimizations should be applied
193
                bool PT_override = false;
25✔
194
                if (System->StageList.size() > 0 &&
57✔
195
                        (System->StageList[0]->ElementList.size() < 10 ||
32✔
196
                         System->StageList.size() == 1))
7✔
197
                {
198
                        PT_override = true;
20✔
199
                }
200

201
                uint_fast64_t update_rate = std::min(
25✔
202
                        std::max(static_cast<uint_fast64_t>(1), NumberOfRays / 10),
50✔
203
                        static_cast<uint_fast64_t>(1000));
25✔
204
                uint_fast64_t update_count = 0;
25✔
205
                double total_work = System->StageList.size() * NumberOfRays;
25✔
206

207
                // Initialize Internal State Variables
208
                uint_fast64_t RayNumber = 1; // Ray Number of current ray
25✔
209
                bool PreviousStageHasRays = false;
25✔
210
                uint_fast64_t LastRayNumberInPreviousStage = NumberOfRays;
25✔
211

212
                // Define IncomingRays
213
                std::vector<GlobalRay_refactored> IncomingRays; // Vector of rays from previous stage, going into next stage
25✔
214
                IncomingRays.resize(NumberOfRays);
25✔
215

216
                // Initialize stage variables
217
                uint_fast64_t StageDataArrayIndex = 0;
25✔
218
                uint_fast64_t PreviousStageDataArrayIndex = 0;
25✔
219
                uint_fast64_t n_rays_active = NumberOfRays;
25✔
220
                uint_fast64_t sun_ray_count_local = 0;
25✔
221

222
                // Loop through stages
223
                for (uint_fast64_t i = 0; i < System->StageList.size(); i++)
65✔
224
                {
225
                        // std::cout << "Processing stage " << i << "..." << std::endl;
226
                        // Check if previous stage has rays
227
                        bool StageHasRays = true;
41✔
228
                        if (i > 0 && PreviousStageHasRays == false)
41✔
229
                        {
230
                                StageHasRays = false;
×
231
                        }
232

233
                        // Get Current Stage
234
                        tstage_ptr Stage = System->StageList[i];
41✔
235

236
                        // Initialize stage variables
237
                        StageDataArrayIndex = 0;
41✔
238
                        PreviousStageDataArrayIndex = 0;
41✔
239

240
                        // Loop through rays
241
                        while (StageHasRays)
11,740,804✔
242
                        {
243
                                // Initialize Global Coordinates
244
                                double PosRayGlob[3] = {0.0, 0.0, 0.0};
11,740,804✔
245
                                double CosRayGlob[3] = {0.0, 0.0, 0.0};
11,740,804✔
246

247
                                // Initialize Stage Coordinates
248
                                double PosRayStage[3] = {0.0, 0.0, 0.0};
11,740,804✔
249
                                double CosRayStage[3] = {0.0, 0.0, 0.0};
11,740,804✔
250

251
                                // Initialize PT Optimization variables
252
                                bool has_elements = true;
11,740,804✔
253
                                std::vector<void *> sunint_elements;
11,740,804✔
254

255
                                // Get Ray
256
                                if (i == 0)
11,740,804✔
257
                                {
258
                                        // TODO: This function seems to ignore the MaxNumberOfRays
259
                                        // argument. Should fix that.
260

261
                                        // Make ray (if first stage)
262
                                        double PosRaySun[3];
263
                                        GenerateRay(myrng, PosSunStage.data, Stage->Origin,
11,019,794✔
264
                                                                Stage->RLocToRef, &System->Sun,
11,019,794✔
265
                                                                PosRayGlob, CosRayGlob, PosRaySun);
266
                                        sun_ray_count_local++;
11,019,794✔
267

268
                                        // If using PT optimizations, check if stage has elements
269
                                        // that could interact with ray
270
                                        if (!PT_override)
11,019,794✔
271
                                        {
272
                                                has_elements =
472,002✔
273
                                                        sun_hash->get_all_data_at_loc(sunint_elements,
472,002✔
274
                                                                                                                  PosRaySun[0],
275
                                                                                                                  PosRaySun[1]);
276
                                        }
277
                                }
278
                                else
279
                                {
280
                                        // Get ray from previous stage
281
                                        RayNumber = IncomingRays[StageDataArrayIndex].Num;
721,010✔
282
                                        CopyVec3(PosRayGlob, IncomingRays[StageDataArrayIndex].Pos);
721,010✔
283
                                        CopyVec3(CosRayGlob, IncomingRays[StageDataArrayIndex].Cos);
721,010✔
284
                                        StageDataArrayIndex++;
721,010✔
285
                                }
286

287
                                // transform the global incoming ray to local stage coordinates
288
                                TransformToLocal(PosRayGlob, CosRayGlob,
11,740,804✔
289
                                                                 Stage->Origin, Stage->RRefToLoc,
11,740,804✔
290
                                                                 PosRayStage, CosRayStage);
291

292
                                // Initialize internal variables for ray intersection tracing
293
                                bool RayInStage = true;
11,740,804✔
294
                                bool in_multi_hit_loop = false;
11,740,804✔
295
                                double LastPosRaySurfElement[3] = {0.0, 0.0, 0.0};
11,740,804✔
296
                                double LastCosRaySurfElement[3] = {0.0, 0.0, 0.0};
11,740,804✔
297
                                double LastPosRaySurfStage[3] = {0.0, 0.0, 0.0};
11,740,804✔
298
                                double LastCosRaySurfStage[3] = {0.0, 0.0, 0.0};
11,740,804✔
299
                                double LastDFXYZ[3] = {0.0, 0.0, 0.0};
11,740,804✔
300
                                uint_fast64_t LastElementNumber = 0;
11,740,804✔
301
                                uint_fast64_t LastRayNumber = 0;
11,740,804✔
302
                                int ErrorFlag;
303
                                int LastHitBackSide;
304
                                bool StageHit;
305
                                int MultipleHitCount = 0;
11,740,804✔
306
                                double PosRayOutElement[3] = {0.0, 0.0, 0.0};
11,740,804✔
307
                                double CosRayOutElement[3] = {0.0, 0.0, 0.0};
11,740,804✔
308

309
                                // Start Loop to trace ray until it leaves stage
310
                                bool RayIsAbsorbed = false;
11,740,804✔
311
                                while (RayInStage)
12,801,587✔
312
                                {
313
                                        // Set number of elements to search through
314
                                        uint_fast64_t nintelements = 0;
12,801,587✔
315
                                        std::vector<void *> reflint_elements;
12,801,587✔
316
                                        if (!PT_override) // if using opt AND first stage
12,801,587✔
317
                                        {
318
                                                nintelements = GetPTElements(AsPowerTower, Stage, i,
620,210✔
319
                                                                                                         in_multi_hit_loop, PosRayStage,
320
                                                                                                         reccm_helio.data, rec_hash,
620,210✔
321
                                                                                                         sunint_elements,
322
                                                                                                         reflint_elements, has_elements);
323
                                        }
324
                                        else
325
                                        {
326
                                                nintelements = Stage->ElementList.size();
12,181,377✔
327
                                        }
328

329
                                        // Find the element the ray hits
330
                                        FindElementHit(i, Stage, PT_override, AsPowerTower,
12,801,587✔
331
                                                                   nintelements, sunint_elements,
332
                                                                   reflint_elements,
333
                                                                   RayNumber, in_multi_hit_loop,
334
                                                                   PosRayStage, CosRayStage,
335
                                                                   LastPosRaySurfElement,
336
                                                                   LastCosRaySurfElement,
337
                                                                   LastDFXYZ,
338
                                                                   LastElementNumber, LastRayNumber,
339
                                                                   LastPosRaySurfStage, LastCosRaySurfStage,
340
                                                                   ErrorFlag, LastHitBackSide, StageHit);
341

342
                                        // Breakout if ray left stage
343
                                        if (!StageHit)
12,801,587✔
344
                                        {
345
                                                RayInStage = false;
10,938,850✔
346
                                                break;
10,938,850✔
347
                                        }
348

349
                                        // Increment MultipleHitCount
350
                                        MultipleHitCount++;
1,862,737✔
351

352
                                        if (i == 0 && MultipleHitCount == 1)
1,862,737✔
353
                                        {
354
                                                auto r = System->RayData.Append(thread_id,
355
                                                                                                                PosRayGlob,
356
                                                                                                                CosRayGlob,
357
                                                                                                                ELEMENT_NULL,
358
                                                                                                                i + 1,
891,011✔
359
                                                                                                                LastRayNumber,
360
                                                                                                                RayEvent::CREATE);
891,011✔
361
                                                if (r == nullptr)
891,011✔
362
                                                {
363
                                                        std::stringstream ss;
×
364
                                                        ss << "Thread " << thread_id
×
365
                                                           << " failed to record ray data.\n";
×
NEW
366
                                                        logger->error_log(ss.str());
×
367
                                                }
×
368
                                        }
891,011✔
369

370
                                        // Get optics and check for absorption
371
                                        const OpticalProperties *optics = 0;
1,862,737✔
372
                                        RayEvent rev = RayEvent::VIRTUAL;
1,862,737✔
373
                                        if (Stage->Virtual)
1,862,737✔
374
                                        {
375
                                                // If stage is virtual, there is no interaction
376
                                                CopyVec3(PosRayOutElement, LastPosRaySurfElement);
15,295✔
377
                                                CopyVec3(CosRayOutElement, LastCosRaySurfElement);
15,295✔
378
                                        }
379
                                        else
380
                                        {
381
                                                // trace through the interaction
382
                                                telement_ptr optelm =
383
                                                        Stage->ElementList[LastElementNumber - 1];
1,847,442✔
384

385
                                                if (LastHitBackSide)
1,847,442✔
386
                                                        optics = &optelm->Optics.Back;
201,732✔
387
                                                else
388
                                                        optics = &optelm->Optics.Front;
1,645,710✔
389

390
                                                bool good = determine_interaction_type(
1,847,442✔
391
                                                        logger,
392
                                                        i,
393
                                                        0,
394
                                                        myrng,
395
                                                        optics,
396
                                                        LastDFXYZ,
397
                                                        LastCosRaySurfElement,
398
                                                        rev);
399

400
                                                if (!good)
1,847,442✔
401
                                                {
UNCOV
402
                                                        return RunnerStatus::ERROR;
×
403
                                                }
404

405
                                                if (rev == RayEvent::ABSORB)
1,847,442✔
406
                                                {
407
                                                        RayIsAbsorbed = true;
787,051✔
408
                                                        break;
787,051✔
409
                                                }
410
                                        }
1,847,442✔
411

412
                                        // Process Interaction
413
                                        int_fast64_t k = LastElementNumber - 1;
1,075,686✔
414
                                        ProcessInteraction(System,
1,075,686✔
415
                                                                           myrng,
416
                                                                           IncludeSunShape,
417
                                                                           optics,
418
                                                                           IncludeErrors,
419
                                                                           i,
420
                                                                           Stage,
421
                                                                           MultipleHitCount,
422
                                                                           LastDFXYZ,
423
                                                                           LastCosRaySurfElement,
424
                                                                           ErrorFlag,
425
                                                                           CosRayOutElement,
426
                                                                           LastPosRaySurfElement,
427
                                                                           PosRayOutElement);
428

429
                                        // Transform ray back to stage coordinate system
430
                                        TransformToReference(PosRayOutElement,
1,075,686✔
431
                                                                                 CosRayOutElement,
432
                                                                                 Stage->ElementList[k]->Origin,
1,075,686✔
433
                                                                                 Stage->ElementList[k]->RLocToRef,
1,075,686✔
434
                                                                                 PosRayStage,
435
                                                                                 CosRayStage);
436
                                        TransformToReference(PosRayStage,
1,075,686✔
437
                                                                                 CosRayStage,
438
                                                                                 Stage->Origin,
1,075,686✔
439
                                                                                 Stage->RLocToRef,
1,075,686✔
440
                                                                                 PosRayGlob,
441
                                                                                 CosRayGlob);
442

443
                                        System->RayData.Append(thread_id,
1,075,686✔
444
                                                                                   PosRayGlob,
445
                                                                                   CosRayGlob,
446
                                                                                   LastElementNumber,
447
                                                                                   i + 1,
1,075,686✔
448
                                                                                   LastRayNumber,
449
                                                                                   rev);
450

451
                                        // Break out if multiple hits are not allowed
452
                                        if (!Stage->MultiHitsPerRay)
1,075,686✔
453
                                        {
454
                                                StageHit = false;
14,903✔
455
                                                break;
14,903✔
456
                                        }
457
                                        else
458
                                        {
459
                                                in_multi_hit_loop = true;
1,060,783✔
460
                                        }
461
                                }
12,801,587✔
462

463
                                if (MultipleHitCount > 0)
11,740,804✔
464
                                        ++update_count;
1,559,132✔
465

466
                                if (update_count % update_rate == 0)
11,740,804✔
467
                                {
468
                                        double progress = update_count / total_work;
11,978✔
469
                                        manager->progress_update(thread_id, progress);
11,978✔
470
                                        if (manager->terminate(thread_id))
11,978✔
471
                                                return RunnerStatus::CANCEL;
1✔
472
                                }
473

474
                                // Handle if Ray was absorbed
475
                                if (RayIsAbsorbed)
11,740,803✔
476
                                {
477
                                        TransformToReference(LastPosRaySurfStage,
787,051✔
478
                                                                                 LastCosRaySurfStage,
479
                                                                                 Stage->Origin,
787,051✔
480
                                                                                 Stage->RLocToRef,
787,051✔
481
                                                                                 PosRayGlob,
482
                                                                                 CosRayGlob);
483

484
                                        System->RayData.Append(thread_id,
787,051✔
485
                                                                                   PosRayGlob,
486
                                                                                   CosRayGlob,
487
                                                                                   LastElementNumber,
488
                                                                                   i + 1,
787,051✔
489
                                                                                   LastRayNumber,
490
                                                                                   RayEvent::ABSORB);
491

492
                                        n_rays_active--;
787,051✔
493

494
                                        // ray was fully absorbed
495
                                        if (RayNumber == LastRayNumberInPreviousStage)
787,051✔
496
                                        {
497
                                                PreviousStageHasRays = false;
16✔
498
                                                if (PreviousStageDataArrayIndex > 0)
16✔
499
                                                {
500
                                                        PreviousStageDataArrayIndex--;
16✔
501
                                                        PreviousStageHasRays = true;
16✔
502
                                                }
503
                                                break;
16✔
504
                                        }
505
                                        else
506
                                        {
507
                                                if (i == 0)
787,035✔
508
                                                {
509
                                                        if (RayNumber == NumberOfRays)
145,522✔
510
                                                                break;
×
511
                                                        else
512
                                                                RayNumber++;
145,522✔
513
                                                }
514

515
                                                // Next ray in loop
516
                                                continue;
787,035✔
517
                                        }
518
                                }
519

520
                                // Ray has left the stage
521
                                bool FlagMiss = false;
10,953,752✔
522
                                if (i == 0)
10,953,752✔
523
                                {
524
                                        if (MultipleHitCount == 0)
10,874,265✔
525
                                        {
526
                                                // Ray in first stage missed stage entirely
527
                                                // Generate new ray
528
                                                continue;
10,128,783✔
529
                                        }
530
                                        else
531
                                        {
532
                                                // Ray hit an element, so save it for next stage
533
                                                CopyVec3(IncomingRays[PreviousStageDataArrayIndex].Pos,
745,482✔
534
                                                                 PosRayGlob);
535
                                                CopyVec3(IncomingRays[PreviousStageDataArrayIndex].Cos,
745,482✔
536
                                                                 CosRayGlob);
537
                                                IncomingRays[PreviousStageDataArrayIndex].Num = RayNumber;
745,482✔
538

539
                                                // Is Ray the last in the stage?
540
                                                if (RayNumber == NumberOfRays)
745,482✔
541
                                                {
542
                                                        StageHasRays = false;
18✔
543
                                                        break;
18✔
544
                                                }
545

546
                                                PreviousStageDataArrayIndex++;
745,464✔
547
                                                PreviousStageHasRays = true;
745,464✔
548

549
                                                // Move on to next ray
550
                                                RayNumber++;
745,464✔
551
                                                continue;
745,464✔
552
                                        }
553
                                }
554
                                else
555
                                {
556
                                        // After the first stage
557
                                        // Ray hit element OR is traced through stage
558
                                        if (Stage->TraceThrough || MultipleHitCount > 0)
79,487✔
559
                                        {
560
                                                // Ray is saved for the next stage
561
                                                CopyVec3(IncomingRays[PreviousStageDataArrayIndex].Pos,
73,131✔
562
                                                                 PosRayGlob);
563
                                                CopyVec3(IncomingRays[PreviousStageDataArrayIndex].Cos,
73,131✔
564
                                                                 CosRayGlob);
565
                                                IncomingRays[PreviousStageDataArrayIndex].Num = RayNumber;
73,131✔
566

567
                                                // Check if ray is last in stage
568
                                                if (RayNumber == LastRayNumberInPreviousStage)
73,131✔
569
                                                {
570
                                                        StageHasRays = false;
5✔
571
                                                        break;
5✔
572
                                                }
573

574
                                                PreviousStageDataArrayIndex++;
73,126✔
575
                                                PreviousStageHasRays = true;
73,126✔
576

577
                                                if (MultipleHitCount == 0)
73,126✔
578
                                                {
579
                                                        FlagMiss = true;
46,529✔
580
                                                }
581

582
                                                // Go to next ray
583
                                                continue;
73,126✔
584
                                        }
585
                                        // Ray missed stage entirely and is not traced
586
                                        else
587
                                        {
588
                                                FlagMiss = true;
6,356✔
589
                                        }
590

591
                                        // Handle FlagMiss condition (
592
                                        if (FlagMiss == true)
6,356✔
593
                                        {
594
                                                LastRayNumber = RayNumber;
6,356✔
595

596
                                                System->RayData.Append(thread_id,
6,356✔
597
                                                                                           PosRayGlob,
598
                                                                                           CosRayGlob,
599
                                                                                           ELEMENT_NULL,
600
                                                                                           i + 1,
6,356✔
601
                                                                                           LastRayNumber,
602
                                                                                           RayEvent::EXIT);
603

604
                                                n_rays_active--;
6,356✔
605

606
                                                if (RayNumber == LastRayNumberInPreviousStage)
6,356✔
607
                                                {
608
                                                        if (!Stage->TraceThrough)
1✔
609
                                                        {
610
                                                                PreviousStageHasRays = false;
1✔
611
                                                                if (PreviousStageDataArrayIndex > 0)
1✔
612
                                                                {
613
                                                                        PreviousStageHasRays = true;
1✔
614
                                                                        PreviousStageDataArrayIndex--; // last ray was previous one
1✔
615
                                                                }
616
                                                        }
617

618
                                                        // Exit stage
619
                                                        StageHasRays = false;
1✔
620
                                                        break;
1✔
621
                                                }
622
                                                else
623
                                                {
624
                                                        if (i == 0)
6,355✔
625
                                                                RayNumber++; // generate new sun ray
×
626

627
                                                        // Start new ray
628
                                                        continue;
6,355✔
629
                                                }
630
                                        }
631
                                }
632
                        }
11,740,804✔
633

634
                        // EndStage section...
635

636
                        // skipping save_st_data logic
637

638
                        if (!PreviousStageHasRays)
40✔
639
                        {
640
                                LastRayNumberInPreviousStage = 0;
1✔
641
                                continue; // No rays to carry forward
1✔
642
                        }
643

644
                        if (PreviousStageDataArrayIndex < IncomingRays.size())
39✔
645
                        {
646
                                LastRayNumberInPreviousStage = IncomingRays[PreviousStageDataArrayIndex].Num;
39✔
647
                                if (LastRayNumberInPreviousStage == 0)
39✔
648
                                {
649
                                        return RunnerStatus::ERROR;
×
650
                                }
651
                        }
652
                        else
653
                        {
654
                                return RunnerStatus::ERROR;
×
655
                        }
656
                }
41✔
657

658
                // Close out any remaining rays as misses
659
                unsigned idx = System->StageList.size() - 1;
24✔
660
                tstage_ptr Stage = System->StageList[idx];
24✔
661
                for (uint_fast64_t k = 0; k < n_rays_active; ++k)
96,774✔
662
                {
663
                        GlobalRay_refactored ray = IncomingRays[k];
96,750✔
664
                        System->RayData.Append(thread_id,
96,750✔
665
                                                                   ray.Pos,
666
                                                                   ray.Cos,
667
                                                                   ELEMENT_NULL,
668
                                                                   idx + 1,
96,750✔
669
                                                                   ray.Num,
670
                                                                   RayEvent::EXIT);
671
                }
672

673
                // System->SunRayCount is atomic so this is thread safe
674
                System->SunRayCount += sun_ray_count_local;
24✔
675

676
                return RunnerStatus::SUCCESS;
24✔
677
        }
25✔
678

679
} // namespace SolTrace::NativeRunner
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

© 2026 Coveralls, Inc