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

NREL / SolTrace / 19436441296

17 Nov 2025 04:15PM UTC coverage: 88.811% (+0.06%) from 88.752%
19436441296

push

github

web-flow
80 add status and cancel functions to simulationrunner api (#81)

* Adding the functions to the SimulationRunner class; stub versions for NativeRunner and OptixRunner

* NativeRunner implementation of status and cancel functions

* Address copilot comments

64 of 70 new or added lines in 6 files covered. (91.43%)

5540 of 6238 relevant lines covered (88.81%)

8562956.42 hits per line

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

94.12
/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 <mutex>
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 "find_element_hit.hpp"
69
#include "generate_ray.hpp"
70
#include "native_runner_types.hpp"
71
#include "process_interaction.hpp"
72
#include "pt_optimizations.hpp"
73
#include "sun_to_primary_stage.hpp"
74
#include "treemesh.hpp"
75

76
namespace SolTrace::NativeRunner
77
{
78

79
        using SolTrace::Result::RayEvent;
80
        using SolTrace::Runner::RunnerStatus;
81

82
        // Trace method
83
        RunnerStatus trace_native(
23✔
84
                TSystem *System,
85
                unsigned int seed,
86
                uint_fast64_t NumberOfRays,
87
                uint_fast64_t MaxNumberOfRays,
88
                bool IncludeSunShape,
89
                bool IncludeErrors,
90
                bool AsPowerTower)
91
        {
92
                // Create isolated scope for lock guard
93
                {
94
                        std::lock_guard<std::mutex> lk(System->state_mutex);
23✔
95
                        System->progress = 0.0;
23✔
96
                        System->cancel = false;
23✔
97
                        System->current_state = RunnerStatus::RUNNING;
23✔
98
                }
23✔
99

100
                // Determine if PT optimizations should be applied
101
                bool PT_override = false;
23✔
102
                if (System->StageList.size() > 0 &&
53✔
103
                        (System->StageList[0]->ElementList.size() < 10 || System->StageList.size() == 1))
30✔
104
                {
105
                        PT_override = true;
18✔
106
                }
107

108
                // Initialize variables
109
                // std::cout << "Seed: " << seed << std::endl;
110
                MTRand myrng(seed);
23✔
111
                int myrng_counter = 0;
23✔
112

113
                uint_fast64_t update_rate = std::min(
23✔
114
                        std::max(static_cast<uint_fast64_t>(1), NumberOfRays / 10),
46✔
115
                        static_cast<uint_fast64_t>(1000));
23✔
116
                uint_fast64_t update_count = 0;
23✔
117
                double total_work = System->StageList.size() * NumberOfRays;
23✔
118

119
                // Initialize Internal State Variables
120
                uint_fast64_t RayNumber = 1; // Ray Number of current ray
23✔
121
                bool PreviousStageHasRays = false;
23✔
122
                uint_fast64_t LastRayNumberInPreviousStage = NumberOfRays;
23✔
123

124
                // Define IncomingRays
125
                std::vector<GlobalRay_refactored> IncomingRays; // Vector of rays from previous stage, going into next stage
23✔
126
                IncomingRays.resize(NumberOfRays);
23✔
127

128
                // Initialize Sun
129
                double PosSunStage[3] = {0.0, 0.0, 0.0};
23✔
130
                if (!SunToPrimaryStage(System,
23✔
131
                                                           System->StageList[0].get(),
23✔
132
                                                           &System->Sun,
133
                                                           PosSunStage))
NEW
134
                        return RunnerStatus::ERROR;
×
135

136
                // Calculate hash tree for reflection to receiver plane(polar coordinates).
137
                st_hash_tree sun_hash;
23✔
138
                st_hash_tree rec_hash;
23✔
139
                double reccm_helio[3]; // receiver centroid in heliostat field coordinates
140
                if (!PT_override)
23✔
141
                {
142
                        SetupPTOptimizations(System, AsPowerTower, sun_hash,
5✔
143
                                                                 rec_hash, reccm_helio);
144
                }
145

146
                // Start the clock
147
                clock_t startTime = clock();
23✔
148
                // int rays_per_callback_estimate = 50;
149
                uint_fast64_t RaysTracedTotal = 0;
23✔
150

151
                // Initialize stage variables
152
                uint_fast64_t StageDataArrayIndex = 0;
23✔
153
                uint_fast64_t PreviousStageDataArrayIndex = 0;
23✔
154
                uint_fast64_t n_rays_active = NumberOfRays;
23✔
155

156
                // Loop through stages
157
                for (uint_fast64_t i = 0; i < System->StageList.size(); i++)
57✔
158
                {
159
                        // std::cout << "Processing stage " << i << "..." << std::endl;
160
                        // Check if previous stage has rays
161
                        bool StageHasRays = true;
35✔
162
                        if (i > 0 && PreviousStageHasRays == false)
35✔
163
                        {
164
                                StageHasRays = false;
×
165
                        }
166

167
                        // Get Current Stage
168
                        tstage_ptr Stage = System->StageList[i];
35✔
169

170
                        // Initialize stage variables
171
                        StageDataArrayIndex = 0;
35✔
172
                        PreviousStageDataArrayIndex = 0;
35✔
173

174
                        // Loop through rays
175
                        while (StageHasRays)
11,785,929✔
176
                        {
177
                                // Initialize Global Coordinates
178
                                double PosRayGlob[3] = {0.0, 0.0, 0.0};
11,785,929✔
179
                                double CosRayGlob[3] = {0.0, 0.0, 0.0};
11,785,929✔
180

181
                                // Initialize Stage Coordinates
182
                                double PosRayStage[3] = {0.0, 0.0, 0.0};
11,785,929✔
183
                                double CosRayStage[3] = {0.0, 0.0, 0.0};
11,785,929✔
184

185
                                // Initialize PT Optimization variables
186
                                bool has_elements = true;
11,785,929✔
187
                                std::vector<void *> sunint_elements;
11,785,929✔
188

189
                                // Get Ray
190
                                if (i == 0)
11,785,929✔
191
                                {
192
                                        // TODO: This function seems to ignore the MaxNumberOfRays
193
                                        // argument. Should fix that.
194

195
                                        // Make ray (if first stage)
196
                                        double PosRaySun[3];
197
                                        GenerateRay(myrng, PosSunStage, Stage->Origin,
11,010,512✔
198
                                                                Stage->RLocToRef, &System->Sun,
11,010,512✔
199
                                                                PosRayGlob, CosRayGlob, PosRaySun);
200
                                        myrng_counter++;
11,010,512✔
201
                                        System->SunRayCount++;
11,010,512✔
202

203
                                        // If using PT optimizations, check if stage has elements
204
                                        // that could interact with ray
205
                                        if (!PT_override)
11,010,512✔
206
                                        {
207
                                                has_elements =
509,140✔
208
                                                        sun_hash.get_all_data_at_loc(sunint_elements,
509,140✔
209
                                                                                                                 PosRaySun[0],
210
                                                                                                                 PosRaySun[1]);
211
                                        }
212
                                }
213
                                else
214
                                {
215
                                        // Get ray from previous stage
216
                                        RayNumber = IncomingRays[StageDataArrayIndex].Num;
775,417✔
217
                                        CopyVec3(PosRayGlob, IncomingRays[StageDataArrayIndex].Pos);
775,417✔
218
                                        CopyVec3(CosRayGlob, IncomingRays[StageDataArrayIndex].Cos);
775,417✔
219
                                        StageDataArrayIndex++;
775,417✔
220
                                }
221

222
                                // transform the global incoming ray to local stage coordinates
223
                                TransformToLocal(PosRayGlob, CosRayGlob,
11,785,929✔
224
                                                                 Stage->Origin, Stage->RRefToLoc,
11,785,929✔
225
                                                                 PosRayStage, CosRayStage);
226

227
                                // Initialize internal variables for ray intersection tracing
228
                                bool RayInStage = true;
11,785,929✔
229
                                bool in_multi_hit_loop = false;
11,785,929✔
230
                                double LastPosRaySurfElement[3] = {0.0, 0.0, 0.0};
11,785,929✔
231
                                double LastCosRaySurfElement[3] = {0.0, 0.0, 0.0};
11,785,929✔
232
                                double LastPosRaySurfStage[3] = {0.0, 0.0, 0.0};
11,785,929✔
233
                                double LastCosRaySurfStage[3] = {0.0, 0.0, 0.0};
11,785,929✔
234
                                double LastDFXYZ[3] = {0.0, 0.0, 0.0};
11,785,929✔
235
                                uint_fast64_t LastElementNumber = 0;
11,785,929✔
236
                                uint_fast64_t LastRayNumber = 0;
11,785,929✔
237
                                int ErrorFlag;
238
                                int LastHitBackSide;
239
                                bool StageHit;
240
                                int MultipleHitCount = 0;
11,785,929✔
241
                                double PosRayOutElement[3] = {0.0, 0.0, 0.0};
11,785,929✔
242
                                double CosRayOutElement[3] = {0.0, 0.0, 0.0};
11,785,929✔
243

244
                                // Start Loop to trace ray until it leaves stage
245
                                bool RayIsAbsorbed = false;
11,785,929✔
246
                                while (RayInStage)
12,971,538✔
247
                                {
248
                                        // Set number of elements to search through
249
                                        uint_fast64_t nintelements = 0;
12,971,538✔
250
                                        std::vector<void *> reflint_elements;
12,971,538✔
251
                                        if (!PT_override) // if using opt AND first stage
12,971,538✔
252
                                        {
253
                                                nintelements = GetPTElements(AsPowerTower, Stage, i,
910,539✔
254
                                                                                                         in_multi_hit_loop, PosRayStage,
255
                                                                                                         reccm_helio, rec_hash,
256
                                                                                                         sunint_elements,
257
                                                                                                         reflint_elements, has_elements);
258
                                        }
259
                                        else
260
                                        {
261
                                                nintelements = Stage->ElementList.size();
12,060,999✔
262
                                        }
263

264
                                        // Find the element the ray hits
265
                                        FindElementHit(i, Stage, PT_override, AsPowerTower,
12,971,538✔
266
                                                                   nintelements, sunint_elements,
267
                                                                   reflint_elements,
268
                                                                   RayNumber, in_multi_hit_loop,
269
                                                                   PosRayStage, CosRayStage,
270
                                                                   LastPosRaySurfElement,
271
                                                                   LastCosRaySurfElement,
272
                                                                   LastDFXYZ,
273
                                                                   LastElementNumber, LastRayNumber,
274
                                                                   LastPosRaySurfStage, LastCosRaySurfStage,
275
                                                                   ErrorFlag, LastHitBackSide, StageHit);
276

277
                                        // Breakout if ray left stage
278
                                        if (!StageHit)
12,971,538✔
279
                                        {
280
                                                RayInStage = false;
10,902,853✔
281
                                                break;
10,902,853✔
282
                                        }
283

284
                                        // Increment MultipleHitCount
285
                                        MultipleHitCount++;
2,068,685✔
286

287
                                        if (i == 0 && MultipleHitCount == 1)
2,068,685✔
288
                                        {
289
                                                System->RayData.Append(PosRayGlob,
960,436✔
290
                                                                                           CosRayGlob,
291
                                                                                           ELEMENT_NULL,
292
                                                                                           i + 1,
960,436✔
293
                                                                                           LastRayNumber,
294
                                                                                           RayEvent::CREATE);
295
                                        }
296

297
                                        // Get optics and check for absorption
298
                                        const OpticalProperties *optics = 0;
2,068,685✔
299
                                        RayEvent rev = RayEvent::VIRTUAL;
2,068,685✔
300
                                        if (Stage->Virtual)
2,068,685✔
301
                                        {
302
                                                // If stage is virtual, there is no interaction
303
                                                CopyVec3(PosRayOutElement, LastPosRaySurfElement);
×
304
                                                CopyVec3(CosRayOutElement, LastCosRaySurfElement);
×
305
                                        }
306
                                        else
307
                                        {
308
                                                // trace through the interaction
309
                                                telement_ptr optelm = Stage->ElementList[LastElementNumber - 1];
2,068,685✔
310

311
                                                if (LastHitBackSide)
2,068,685✔
312
                                                        optics = &optelm->Optics.Back;
332,720✔
313
                                                else
314
                                                        optics = &optelm->Optics.Front;
1,735,965✔
315

316
                                                double TestValue;
317
                                                double UnitLastDFXYZ[3] = {0.0, 0.0, 0.0};
2,068,685✔
318
                                                double IncidentAngle = 0;
2,068,685✔
319
                                                // switch (optelm->InteractionType)
320
                                                switch (optics->my_type)
2,068,685✔
321
                                                {
322
                                                case InteractionType::REFRACTION: // refraction
194,853✔
323
                                                        // TODO: Implement transmissivity table?
324
                                                        // if (optics->UseTransmissivityTable)
325
                                                        // {
326
                                                        //         int npoints = optics->TransmissivityTable.size();
327
                                                        //         int m = 0;
328

329
                                                        //         UnitLastDFXYZ[0] = -LastDFXYZ[0] / sqrt(DOT(LastDFXYZ, LastDFXYZ));
330
                                                        //         UnitLastDFXYZ[1] = -LastDFXYZ[1] / sqrt(DOT(LastDFXYZ, LastDFXYZ));
331
                                                        //         UnitLastDFXYZ[2] = -LastDFXYZ[2] / sqrt(DOT(LastDFXYZ, LastDFXYZ));
332
                                                        //         IncidentAngle = acos(DOT(LastCosRaySurfElement, UnitLastDFXYZ)) * 1000.; //[mrad]
333
                                                        //         if (IncidentAngle >= optics->TransmissivityTable[npoints - 1].angle)
334
                                                        //         {
335
                                                        //                 TestValue = optics->TransmissivityTable[npoints - 1].trans;
336
                                                        //         }
337
                                                        //         else
338
                                                        //         {
339
                                                        //                 while (optics->TransmissivityTable[m].angle < IncidentAngle)
340
                                                        //                         m++;
341

342
                                                        //                 if (m == 0)
343
                                                        //                         TestValue = optics->TransmissivityTable[m].trans;
344
                                                        //                 else
345
                                                        //                         TestValue = (optics->TransmissivityTable[m].trans + optics->TransmissivityTable[m - 1].trans) / 2.0;
346
                                                        //         }
347
                                                        // }
348
                                                        // else
349
                                                        //         TestValue = optics->Transmissivity;
350
                                                        TestValue = optics->transmitivity;
194,853✔
351
                                                        rev = RayEvent::TRANSMIT;
194,853✔
352
                                                        break;
194,853✔
353
                                                case InteractionType::REFLECTION: // reflection
1,873,832✔
354
                                                        // TODO: Implement reflectivity table?
355
                                                        // if (optics->UseReflectivityTable)
356
                                                        // {
357
                                                        //         int npoints = optics->ReflectivityTable.size();
358
                                                        //         int m = 0;
359
                                                        //         UnitLastDFXYZ[0] = -LastDFXYZ[0] / sqrt(DOT(LastDFXYZ, LastDFXYZ));
360
                                                        //         UnitLastDFXYZ[1] = -LastDFXYZ[1] / sqrt(DOT(LastDFXYZ, LastDFXYZ));
361
                                                        //         UnitLastDFXYZ[2] = -LastDFXYZ[2] / sqrt(DOT(LastDFXYZ, LastDFXYZ));
362
                                                        //         IncidentAngle = acos(DOT(LastCosRaySurfElement, UnitLastDFXYZ)) * 1000.; //[mrad]
363
                                                        //         if (IncidentAngle >= optics->ReflectivityTable[npoints - 1].angle)
364
                                                        //         {
365
                                                        //                 TestValue = optics->ReflectivityTable[npoints - 1].refl;
366
                                                        //         }
367
                                                        //         else
368
                                                        //         {
369
                                                        //                 while (optics->ReflectivityTable[m].angle < IncidentAngle)
370
                                                        //                         m++;
371

372
                                                        //                 if (m == 0)
373
                                                        //                         TestValue = optics->ReflectivityTable[m].refl;
374
                                                        //                 else
375
                                                        //                         TestValue = (optics->ReflectivityTable[m].refl + optics->ReflectivityTable[m - 1].refl) / 2.0;
376
                                                        //         }
377
                                                        // }
378
                                                        // else
379
                                                        //         TestValue = optics->Reflectivity;
380
                                                        TestValue = optics->reflectivity;
1,873,832✔
381
                                                        rev = RayEvent::REFLECT;
1,873,832✔
382
                                                        break;
1,873,832✔
383
                                                default:
×
384
                                                        System->errlog(
×
385
                                                                "Bad optical interaction type = %d (stage %d)",
386
                                                                i, optics->my_type);
NEW
387
                                                        return RunnerStatus::ERROR;
×
388
                                                }
389

390
                                                // Apply MonteCarlo probability of absorption. Limited
391
                                                // for now, but can make more complex later on if desired
392
                                                // if (TestValue <= myrng())
393
                                                double flip = myrng();
2,068,685✔
394
                                                if (TestValue <= flip)
2,068,685✔
395
                                                {
396
                                                        myrng_counter++;
870,868✔
397
                                                        // ray was fully absorbed
398
                                                        RayIsAbsorbed = true;
870,868✔
399
                                                        break;
870,868✔
400
                                                }
401
                                        }
2,068,685✔
402

403
                                        // Process Interaction
404
                                        int_fast64_t k = LastElementNumber - 1;
1,197,817✔
405
                                        ProcessInteraction(System, myrng, IncludeSunShape,
1,197,817✔
406
                                                                           optics,
407
                                                                           IncludeErrors,
408
                                                                           i, Stage, // k,
409
                                                                           MultipleHitCount, LastDFXYZ,
410
                                                                           LastCosRaySurfElement, ErrorFlag,
411
                                                                           CosRayOutElement, LastPosRaySurfElement,
412
                                                                           PosRayOutElement, myrng_counter);
413

414
                                        // Transform ray back to stage coordinate system
415
                                        TransformToReference(PosRayOutElement, CosRayOutElement,
1,197,817✔
416
                                                                                 Stage->ElementList[k]->Origin,
1,197,817✔
417
                                                                                 Stage->ElementList[k]->RLocToRef,
1,197,817✔
418
                                                                                 PosRayStage, CosRayStage);
419
                                        TransformToReference(PosRayStage, CosRayStage,
1,197,817✔
420
                                                                                 Stage->Origin, Stage->RLocToRef,
1,197,817✔
421
                                                                                 PosRayGlob, CosRayGlob);
422

423
                                        System->RayData.Append(PosRayGlob,
1,197,817✔
424
                                                                                   CosRayGlob,
425
                                                                                   LastElementNumber,
426
                                                                                   i + 1,
1,197,817✔
427
                                                                                   LastRayNumber,
428
                                                                                   rev);
429

430
                                        // Break out if multiple hits are not allowed
431
                                        if (!Stage->MultiHitsPerRay)
1,197,817✔
432
                                        {
433
                                                StageHit = false;
12,208✔
434
                                                break;
12,208✔
435
                                        }
436
                                        else
437
                                        {
438
                                                in_multi_hit_loop = true;
1,185,609✔
439
                                        }
440
                                }
12,971,538✔
441

442
                                ++update_count;
11,785,929✔
443
                                if (update_count % update_rate == 0)
11,785,929✔
444
                                {
445
                                        double progress = update_count / total_work;
11,808✔
446
                                        std::lock_guard<std::mutex> lk(System->state_mutex);
11,808✔
447
                                        if (System->cancel)
11,808✔
448
                                        {
449
                                                return RunnerStatus::CANCEL;
1✔
450
                                        }
451
                                        else
452
                                        {
453
                                                System->progress = progress;
11,807✔
454
                                        }
455
                                }
11,808✔
456

457
                                // Handle if Ray was absorbed
458
                                if (RayIsAbsorbed)
11,785,928✔
459
                                {
460
                                        TransformToReference(LastPosRaySurfStage,
870,868✔
461
                                                                                 LastCosRaySurfStage,
462
                                                                                 Stage->Origin,
870,868✔
463
                                                                                 Stage->RLocToRef,
870,868✔
464
                                                                                 PosRayGlob,
465
                                                                                 CosRayGlob);
466

467
                                        System->RayData.Append(PosRayGlob,
870,868✔
468
                                                                                   CosRayGlob,
469
                                                                                   LastElementNumber,
470
                                                                                   i + 1,
870,868✔
471
                                                                                   LastRayNumber,
472
                                                                                   RayEvent::ABSORB);
473

474
                                        n_rays_active--;
870,868✔
475

476
                                        // ray was fully absorbed
477
                                        if (RayNumber == LastRayNumberInPreviousStage)
870,868✔
478
                                        {
479
                                                PreviousStageHasRays = false;
17✔
480
                                                if (PreviousStageDataArrayIndex > 0)
17✔
481
                                                {
482
                                                        PreviousStageDataArrayIndex--;
16✔
483
                                                        PreviousStageHasRays = true;
16✔
484
                                                }
485
                                                break;
17✔
486
                                        }
487
                                        else
488
                                        {
489
                                                if (i == 0)
870,851✔
490
                                                {
491
                                                        if (RayNumber == NumberOfRays)
142,997✔
492
                                                                break;
×
493
                                                        else
494
                                                                RayNumber++;
142,997✔
495
                                                }
496

497
                                                // Next ray in loop
498
                                                continue;
870,851✔
499
                                        }
500
                                }
501

502
                                // Ray has left the stage
503
                                bool FlagMiss = false;
10,915,060✔
504
                                if (i == 0)
10,915,060✔
505
                                {
506
                                        if (MultipleHitCount == 0)
10,867,508✔
507
                                        {
508
                                                // Ray in first stage missed stage entirely
509
                                                // Generate new ray
510
                                                continue;
10,050,075✔
511
                                        }
512
                                        else
513
                                        {
514
                                                // Ray hit an element, so save it for next stage
515
                                                CopyVec3(IncomingRays[PreviousStageDataArrayIndex].Pos,
817,433✔
516
                                                                 PosRayGlob);
517
                                                CopyVec3(IncomingRays[PreviousStageDataArrayIndex].Cos,
817,433✔
518
                                                                 CosRayGlob);
519
                                                IncomingRays[PreviousStageDataArrayIndex].Num = RayNumber;
817,433✔
520

521
                                                // Is Ray the last in the stage?
522
                                                if (RayNumber == NumberOfRays)
817,433✔
523
                                                {
524
                                                        StageHasRays = false;
16✔
525
                                                        break;
16✔
526
                                                }
527

528
                                                PreviousStageDataArrayIndex++;
817,417✔
529
                                                PreviousStageHasRays = true;
817,417✔
530

531
                                                // Move on to next ray
532
                                                RayNumber++;
817,417✔
533
                                                continue;
817,417✔
534
                                        }
535
                                }
536
                                else
537
                                {
538
                                        // After the first stage
539
                                        // Ray hit element OR is traced through stage
540
                                        if (Stage->TraceThrough || MultipleHitCount > 0)
47,552✔
541
                                        {
542
                                                // Ray is saved for the next stage
543
                                                CopyVec3(IncomingRays[PreviousStageDataArrayIndex].Pos,
41,196✔
544
                                                                 PosRayGlob);
545
                                                CopyVec3(IncomingRays[PreviousStageDataArrayIndex].Cos,
41,196✔
546
                                                                 CosRayGlob);
547
                                                IncomingRays[PreviousStageDataArrayIndex].Num = RayNumber;
41,196✔
548

549
                                                // Check if ray is last in stage
550
                                                if (RayNumber == LastRayNumberInPreviousStage)
41,196✔
551
                                                {
552
                                                        StageHasRays = false;
×
553
                                                        break;
×
554
                                                }
555

556
                                                PreviousStageDataArrayIndex++;
41,196✔
557
                                                PreviousStageHasRays = true;
41,196✔
558

559
                                                if (MultipleHitCount == 0)
41,196✔
560
                                                {
561
                                                        FlagMiss = true;
35,831✔
562
                                                }
563

564
                                                // Go to next ray
565
                                                continue;
41,196✔
566
                                        }
567
                                        // Ray missed stage entirely and is not traced
568
                                        else
569
                                        {
570
                                                FlagMiss = true;
6,356✔
571
                                        }
572

573
                                        // Handle FlagMiss condition (
574
                                        if (FlagMiss == true)
6,356✔
575
                                        {
576
                                                LastRayNumber = RayNumber;
6,356✔
577

578
                                                System->RayData.Append(PosRayGlob,
6,356✔
579
                                                                                           CosRayGlob,
580
                                                                                           ELEMENT_NULL,
581
                                                                                           i + 1,
6,356✔
582
                                                                                           LastRayNumber,
583
                                                                                           RayEvent::EXIT);
584

585
                                                n_rays_active--;
6,356✔
586

587
                                                if (RayNumber == LastRayNumberInPreviousStage)
6,356✔
588
                                                {
589
                                                        if (!Stage->TraceThrough)
1✔
590
                                                        {
591
                                                                PreviousStageHasRays = false;
1✔
592
                                                                if (PreviousStageDataArrayIndex > 0)
1✔
593
                                                                {
594
                                                                        PreviousStageHasRays = true;
1✔
595
                                                                        PreviousStageDataArrayIndex--; // last ray was previous one
1✔
596
                                                                }
597
                                                        }
598

599
                                                        // Exit stage
600
                                                        StageHasRays = false;
1✔
601
                                                        break;
1✔
602
                                                }
603
                                                else
604
                                                {
605
                                                        if (i == 0)
6,355✔
606
                                                                RayNumber++; // generate new sun ray
×
607

608
                                                        // Start new ray
609
                                                        continue;
6,355✔
610
                                                }
611
                                        }
612
                                }
613
                        }
11,785,929✔
614

615
                        // EndStage section...
616

617
                        // skipping save_st_data logic
618

619
                        if (!PreviousStageHasRays)
34✔
620
                        {
621
                                LastRayNumberInPreviousStage = 0;
2✔
622
                                continue; // No rays to carry forward
2✔
623
                        }
624

625
                        if (PreviousStageDataArrayIndex < IncomingRays.size())
32✔
626
                        {
627
                                LastRayNumberInPreviousStage = IncomingRays[PreviousStageDataArrayIndex].Num;
32✔
628
                                if (LastRayNumberInPreviousStage == 0)
32✔
629
                                {
NEW
630
                                        return RunnerStatus::ERROR;
×
631
                                }
632
                        }
633
                        else
634
                        {
NEW
635
                                return RunnerStatus::ERROR;
×
636
                        }
637
                }
35✔
638

639
                // Close out any remaining rays as misses
640
                unsigned idx = System->StageList.size() - 1;
22✔
641
                tstage_ptr Stage = System->StageList[idx];
22✔
642
                for (uint_fast64_t k = 0; k < n_rays_active; ++k)
82,875✔
643
                {
644
                        GlobalRay_refactored ray = IncomingRays[k];
82,853✔
645
                        System->RayData.Append(ray.Pos,
82,853✔
646
                                                                   ray.Cos,
647
                                                                   ELEMENT_NULL,
648
                                                                   idx + 1,
82,853✔
649
                                                                   ray.Num,
82,853✔
650
                                                                   RayEvent::EXIT);
651
                }
652

653
                return RunnerStatus::SUCCESS;
22✔
654
        }
23✔
655

656
} // 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