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

NREL / SolTrace / 14868779160

06 May 2025 08:10PM UTC coverage: 44.154% (+0.5%) from 43.617%
14868779160

Pull #65

github

web-flow
Merge 8d1b66799 into 96166e291
Pull Request #65: Refactor the Trace function (and related functions)

363 of 670 new or added lines in 6 files covered. (54.18%)

135 existing lines in 4 files now uncovered.

1941 of 4396 relevant lines covered (44.15%)

10000057.3 hits per line

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

45.47
/coretrace/raytrace.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

51

52
#include <vector>
53
#include <string>
54
#include <cstdio>
55
#include <cstdlib>
56
#include <cstring>
57
#include <cmath>
58
#include <algorithm>
59
#include <ctime>
60
//#define WITH_DEBUG_TIMER
61
#ifdef WITH_DEBUG_TIMER
62
    #include <chrono>    //comment out for production
63
#endif
64

65
#include "types.h"
66
#include "procs.h"
67
#include "treemesh.h"
68

69

70
void time(const char *message, ofstream *fout)
2✔
71
{
72
#ifdef WITH_DEBUG_TIMER
73
    (*fout) << message << chrono::duration_cast< chrono::milliseconds >( chrono::system_clock::now().time_since_epoch() ).count() << "\n"; 
74
#endif
75
}
2✔
76

77
inline void CopyVec3( double dest[3], const std::vector<double> &src )
78
{
79
        dest[0] = src[0];
80
        dest[1] = src[1];
81
        dest[2] = src[2];
82
}
83

84
inline void CopyVec3( std::vector<double> &dest, double src[3] )
85
{
86
        dest[0] = src[0];
87
        dest[1] = src[1];
88
        dest[2] = src[2];
89
}
90

91
inline void CopyVec3( double dest[3], double src[3] )
1,844,591✔
92
{
93
        dest[0] = src[0];
1,844,591✔
94
        dest[1] = src[1];
1,844,591✔
95
        dest[2] = src[2];
1,844,591✔
96
}
1,844,591✔
97

98
#define ZeroVec(x) x[0]=x[1]=x[2]=0.0
99

100
class GlobalRay
101
{
102
public:
103
        GlobalRay() {
10,000✔
104
                Num = 0;
10,000✔
105
                for (int i=0;i<3;i++) Pos[i]=Cos[i]=0.0;
40,000✔
106
        }
10,000✔
107

108
        double Pos[3];
109
        double Cos[3];
110
        st_uint_t Num;
111
};
112

113
//structure to store element address and projected polar coordinate size
114
struct eprojdat
115
{
116
    TElement* el_addr;
117
    double d_proj;
118
    double az;
119
    double zen;
120

121
    eprojdat(){};
122
    eprojdat(TElement* e, double d, double a, double z)
6,282✔
123
    {
6,282✔
124
        el_addr = e;
6,282✔
125
        d_proj = d;
6,282✔
126
        az = a;
6,282✔
127
        zen = z;
6,282✔
128
    };
6,282✔
129
};
130

131
//Comparison function for sorting vector of eprojdat
UNCOV
132
static bool eprojdat_compare(const eprojdat &A, const eprojdat &B)
×
133
{
UNCOV
134
    return A.d_proj > B.d_proj;
×
135
};
136

137
bool Trace(TSystem *System, unsigned int seed,
1✔
138
                   st_uint_t NumberOfRays, 
139
                   st_uint_t MaxNumberOfRays,
140
                   bool IncludeSunShape, 
141
                   bool IncludeErrors,
142
           bool AsPowerTower,
143
                   int (*callback)(st_uint_t ntracedtotal, st_uint_t ntraced, st_uint_t ntotrace, st_uint_t curstage, st_uint_t nstages, void *data),
144
                   void *cbdata,
145
           std::vector< std::vector< double > > *st0data,
146
           std::vector< std::vector< double > > *st1in,
147
           bool save_st_data)
148
{
149
    
150
    bool PT_override = false;        //override speed improvements (use as compiled option for benchmarking old version)
1✔
151
    
152
    //don't try to use the element filtering method if: 
153
    if( System->StageList.size() > 0 
1✔
154
                && (System->StageList[0]->ElementList.size() < 10    //the first stage contains only a few elements
1✔
UNCOV
155
                        || System->StageList.size() == 1)                //there's only one stage
×
156
      )
157
        PT_override = true;         
1✔
158

159
    bool load_st_data = st0data != 0 && st1in != 0;
1✔
160
    if(load_st_data)
1✔
161
    {
162
        load_st_data = st0data->size() > 0 && st1in->size() > 0;
×
163
    }
164
        bool StageHit = false;
1✔
165
        st_uint_t LastElementNumber = 0, LastRayNumber = 0;
1✔
166
        st_uint_t MultipleHitCount = 0;
1✔
167
        double LastPathLength = 0.0, PathLength = 0.0;
1✔
168

169
        double PosSunStage[3] = { 0.0, 0.0, 0.0 };
1✔
170
        double PosRayOutElement[3] = { 0.0, 0.0, 0.0 };
1✔
171
        double CosRayOutElement[3] = { 0.0, 0.0, 0.0 };
1✔
172
        double CosIn[3] = { 0.0, 0.0, 0.0 };
1✔
173
        double CosOut[3] = { 0.0, 0.0, 0.0 };
1✔
174
        double PosRayGlob[3] = { 0.0, 0.0, 0.0 };
1✔
175
        double CosRayGlob[3] = { 0.0, 0.0, 0.0 };
1✔
176
        double PosRayStage[3] = { 0.0, 0.0, 0.0 };
1✔
177
        double CosRayStage[3] = { 0.0, 0.0, 0.0 };
1✔
178
        double PosRayElement[3] = { 0.0, 0.0, 0.0 };
1✔
179
        double CosRayElement[3] = { 0.0, 0.0, 0.0 };
1✔
180
        double PosRaySurfElement[3] = { 0.0, 0.0, 0.0 };
1✔
181
        double CosRaySurfElement[3] = { 0.0, 0.0, 0.0 };
1✔
182
        double LastPosRaySurfElement[3] = { 0.0, 0.0, 0.0 };
1✔
183
        double LastCosRaySurfElement[3] = { 0.0, 0.0, 0.0 };
1✔
184
        double LastPosRaySurfStage[3] = { 0.0, 0.0, 0.0 };
1✔
185
        double LastCosRaySurfStage[3] = { 0.0, 0.0, 0.0 };
1✔
186
        double PosRaySurfStage[3] = { 0.0, 0.0, 0.0 };
1✔
187
        double CosRaySurfStage[3] = { 0.0, 0.0, 0.0 };
1✔
188
        double DFXYZ[3] = { 0.0, 0.0, 0.0 };
1✔
189
        double LastDFXYZ[3] = { 0.0, 0.0, 0.0 };
1✔
190
        double IncidentAngle = 0.0;
1✔
191
        double UnitLastDFXYZ[3] = { 0.0, 0.0, 0.0 };
1✔
192
        int ErrorFlag = 0, InterceptFlag = 0, HitBackSide = 0, LastHitBackSide = 0;
1✔
193

194
        std::vector<GlobalRay> IncomingRays;
1✔
195
        st_uint_t StageDataArrayIndex=0;
1✔
196
        bool PreviousStageHasRays = false;
1✔
197
        st_uint_t PreviousStageDataArrayIndex = 0;
1✔
198
        st_uint_t LastRayNumberInPreviousStage = NumberOfRays;
1✔
199

200
        ZeroVec( LastPosRaySurfStage );
1✔
201
        ZeroVec( LastCosRaySurfStage );
1✔
202

203
        //bool aspowertower_ok = false;
204
        bool in_multi_hit_loop = false;
1✔
205

206

207
        try
208
        {
209
                TOpticalProperties *optics=NULL;
1✔
210
                PreviousStageHasRays = false;
1✔
211

212
                int k = 0;
1✔
213
                TElement *optelm = 0;
1✔
214
                TRayData::ray_t *p_ray = 0;
1✔
215
                TStage *Stage;
216

217
                System->SunRayCount=0;
1✔
218
                st_uint_t RayNumber = 1;
1✔
219
                MTRand myrng(seed);
1✔
220
                st_uint_t RaysTracedTotal = 0;
1✔
221

222
        if( load_st_data && st0data->size() < 1)
1✔
223
        {
224
            System->errlog("empty stage 0 data array provided to Trace()");
×
225
            return false;
×
226
        }
227
        if( load_st_data && st1in->size() < 1 )
1✔
228
        {
229
            System->errlog("empty stage 1 data array provided to Trace()");
×
230
            return false;
×
231
        }
232

233
                if (NumberOfRays < 1)
1✔
234
                {
235
                        System->errlog("invalid number of rays: %d", NumberOfRays);
×
236
                        return false;
×
237
                }
238

239
                if (System->StageList.size() < 1)
1✔
240
                {
241
                        System->errlog("no stages defined.");
×
242
                        return false;
×
243
                }
244

245
                try
246
                {
247
                        IncomingRays.resize( NumberOfRays );
1✔
248
                } catch (std::exception &e) {
×
249
                        System->errlog("Incoming rays resize exception: %d, '%s'", NumberOfRays, e.what());
×
250
                        return false;
×
251
                }
×
252

253

254
                if (!SunToPrimaryStage(System, System->StageList[0], &System->Sun, PosSunStage))
1✔
255
                        return false;
×
256

257
#ifdef WITH_DEBUG_TIMER
258
        ofstream fout("C:\\Users\\mwagner\\Documents\\NREL\\Dev\\SolTraceWX\\log.txt");
259
        fout.clear();
260
#else 
261
        ofstream fout;
1✔
262
#endif
263

264
        time("Initialize:\t", &fout);
1✔
265

266
        /* 
267
        Calculate hash tree for sun incoming plane.
268
        
269
        Calculate hash tree for reflection to receiver plane (polar coordinates).
270
        */
271
        st_hash_tree sun_hash;
1✔
272
        st_hash_tree rec_hash;
1✔
273
        double reccm_helio[3];  //receiver centroid in heliostat field coordinates
274
        if(! PT_override )
1✔
275
        {
276
            //Calculate the center of mass of the receiver stage (StageList[1]) in heliostat stage coordinates.
UNCOV
277
            double reccm[] = {0., 0., 0.};
×
UNCOV
278
            int nelrec=0;
×
UNCOV
279
            if(AsPowerTower)
×
280
            {
UNCOV
281
                for(st_uint_t j=0; j<System->StageList[1]->ElementList.size(); j++)
×
282
                {
UNCOV
283
                    TElement* el = System->StageList[1]->ElementList.at(j);
×
284

UNCOV
285
                    if(! el->Enabled)
×
286
                        continue;
×
287
                
UNCOV
288
                    nelrec++;
×
289

UNCOV
290
                    for(int jj=0; jj<3; jj++)
×
UNCOV
291
                        reccm[jj] += el->Origin[jj]; 
×
292
                }
UNCOV
293
                for(int jj=0; jj<3; jj++)
×
UNCOV
294
                    reccm[jj] /= (double)nelrec;    //average
×
295
            
296

297
                //Transform to reference 
UNCOV
298
                double dum1[] = {0., 0., 1.};
×
299
                double dum2[3];
300
                double reccm_global[3];
UNCOV
301
                TransformToReference(reccm, dum1, System->StageList[1]->Origin, System->StageList[1]->RLocToRef, reccm_global, dum2);
×
302

303
                //Transform to local (heliostat). reccm_helio is the x,y,z position of the receiver centroid in heliostat stage coordinates.
UNCOV
304
                TransformToLocal(reccm_global, dum1, System->StageList[0]->Origin, System->StageList[0]->RRefToLoc, reccm_helio, dum2);
×
305
            }
306
            //Create an array that stores the element address and the projected size in polar coordinates
UNCOV
307
            vector<eprojdat> el_proj_dat;
×
UNCOV
308
            el_proj_dat.reserve( System->StageList[0]->ElementList.size() );
×
309

310
            //calculate the smallest zone size. This should be on the order of the largest element in the stage. 
311
            //load stage 0 elements into the mesh
UNCOV
312
            double d_elm_max = -9.e9;
×
313

UNCOV
314
            time("Calculating element sizes:\t", &fout);
×
315

UNCOV
316
            for( st_uint_t i=0; i<System->StageList[0]->ElementList.size(); i++)
×
317
            {
UNCOV
318
                TElement* el = System->StageList[0]->ElementList.at(i);
×
319

UNCOV
320
                el->element_number = i+1;   //use index for element number
×
321

322
                double d_elm;
323

UNCOV
324
                switch (el->ShapeIndex)
×
325
                {
326
                //circular aperture
327
                case 'c':
×
328
                case 'C':
329
                //hexagonal aperture
330
                case 'h':
331
                case 'H':
332
                //triangular aperture
333
                case 't':
334
                case 'T':
335
                    d_elm =  el->ParameterA;
×
336
                    break;
×
337
                //rectangular aperture
UNCOV
338
                case 'r':
×
339
                case 'R':
UNCOV
340
                    d_elm =  sqrt(el->ParameterA*el->ParameterA + el->ParameterB*el->ParameterB);
×
UNCOV
341
                    break;
×
342
                //annular aperture
343
                case 'a':
×
344
                case 'A':
345
                    d_elm =  el->ParameterB;
×
346
                    break;
×
347
                case 'l':
×
348
                case 'L': 
349
                    //off axis aperture section of line focus trough  or cylinder
350
                    d_elm =  sqrt(el->ParameterB*el->ParameterB*4. + el->ParameterC*el->ParameterC);
×
351
                    break;
×
352
                //Irregular triangle
353
                case 'i':
×
354
                case 'I':
355
                //irregular quadrilateral
356
                case 'q':
357
                case 'Q':
358
                {
359
                    double xmax = fmax( el->ParameterA, fmax( el->ParameterC, el->ParameterE ) );
×
360
                    double xmin = fmin( el->ParameterA, fmin( el->ParameterC, el->ParameterE ) );
×
361
                    double ymax = fmax( el->ParameterB, fmax( el->ParameterD, el->ParameterF ) );
×
362
                    double ymin = fmin( el->ParameterB, fmin( el->ParameterD, el->ParameterF ) );
×
363

364
                    if( el->ShapeIndex == 'q' || el->ShapeIndex == 'Q' )
×
365
                    {
366
                        xmax = fmax(xmax, el->ParameterG);
×
367
                        xmin = fmin(xmin, el->ParameterG);
×
368
                        ymax = fmax(ymax, el->ParameterH);
×
369
                        ymin = fmin(ymin, el->ParameterH);
×
370
                    }
371

372
                    double dx = xmax - xmin;
×
373
                    double dy = ymax - ymin; 
×
374

375
                    d_elm =  sqrt(dx*dx + dy*dy);
×
376
                
377
                    break;
×
378
                }
379
                default:
×
380
                    break;
×
381
                }
382

UNCOV
383
                d_elm_max = fmax(d_elm_max, d_elm);
×
384
                
UNCOV
385
                if(AsPowerTower)
×
386
                {
387
                    //Calculate the distance from the receiver to the element and the max projected size
388
                    double dX[3];
UNCOV
389
                    for(int jj=0; jj<3; jj++)
×
UNCOV
390
                        dX[jj] = el->Origin[jj] - reccm_helio[jj];  //vector from receiver to heliostat (not unitized)
×
UNCOV
391
                    double r_elm = 0.;
×
UNCOV
392
                    for(int jj=0; jj<3; jj++)
×
UNCOV
393
                        r_elm += dX[jj]*dX[jj];     
×
UNCOV
394
                    r_elm = sqrt(r_elm);            //vector length
×
UNCOV
395
                    double d_elm_proj = d_elm / r_elm;  //Projected size of the element from the view of the receiver (radians)
×
396
                
397
                    //calculate az,zen coordinate
398
                    double az,zen;
UNCOV
399
                    az = atan2(dX[0]/r_elm, dX[1]/r_elm);       //Az coordinate of the heliostat from the receiver's perspective
×
UNCOV
400
                    zen = asin(dX[2]/r_elm);                    //Zen coordinate """"
×
401

UNCOV
402
                    el_proj_dat.push_back( eprojdat(el, d_elm_proj, az, zen) );
×
403
                }
404
            }
405

UNCOV
406
            if(AsPowerTower)
×
407
            {
UNCOV
408
                time("Sorting polar mesh entries:\t", &fout);
×
409

410
                //Sort the polar projections by size, largest to smallest
UNCOV
411
                std::sort(el_proj_dat.begin(), el_proj_dat.end(), eprojdat_compare);
×
412
            }
413

414
            //set up the layout data object that provides configuration details for the hash tree
415
            KDLayoutData sun_ld;
UNCOV
416
            sun_ld.xlim[0] = System->Sun.MinXSun;
×
UNCOV
417
            sun_ld.xlim[1] = System->Sun.MaxXSun;
×
UNCOV
418
            sun_ld.ylim[0] = System->Sun.MinYSun;
×
UNCOV
419
            sun_ld.ylim[1] = System->Sun.MaxYSun;
×
UNCOV
420
            sun_ld.min_unit_dx = d_elm_max;
×
UNCOV
421
            sun_ld.min_unit_dy = d_elm_max;
×
422

UNCOV
423
            sun_hash.create_mesh( sun_ld );
×
UNCOV
424
            time("Adding solar mesh elements:\t", &fout);
×
425
            
426
           //load stage 0 elements into the mesh
UNCOV
427
            for( st_uint_t i=0; i<System->StageList[0]->ElementList.size(); i++)
×
428
            {
UNCOV
429
                TElement* el = System->StageList[0]->ElementList.at(i);
×
UNCOV
430
                sun_hash.add_object( (void*)el, el->PosSunCoords[0], el->PosSunCoords[1] );
×
431
            }
432

433
            //calculate and associate neighbors with each zone
UNCOV
434
            time("Adding solar mesh neighbors:\t", &fout);
×
UNCOV
435
            sun_hash.add_neighborhood_data();
×
436

UNCOV
437
            if(AsPowerTower)
×
438
            {
439
                //Set things up for the polar coordinate tree
440
                KDLayoutData rec_ld;
UNCOV
441
                rec_ld.xlim[0] = -M_PI;
×
UNCOV
442
                rec_ld.xlim[1] = M_PI;
×
UNCOV
443
                rec_ld.ylim[0] = -M_PI/2.;
×
UNCOV
444
                rec_ld.ylim[1] = M_PI/2.;
×
445
                //use smallest element to set the minimum size
UNCOV
446
                rec_ld.min_unit_dx = rec_ld.min_unit_dy = el_proj_dat.back().d_proj; //radians at equator
×
447
            
UNCOV
448
                rec_hash.create_mesh( rec_ld );
×
UNCOV
449
                time("Adding polar mesh elements:\t", &fout);
×
450

451
                //load stage 0 elements into the receiver mesh in the order of largest projection to smallest
UNCOV
452
                for( int i=0; i<el_proj_dat.size(); i++)
×
453
                {
UNCOV
454
                    eprojdat* D = &el_proj_dat.at(i);
×
455

456
                    //Calculate the angular span of the element
457
                    double angspan[2];
UNCOV
458
                    double adjmult = 1.5;
×
UNCOV
459
                    angspan[0] = D->d_proj/cos(fabs(D->zen))*adjmult;   //azimuthal span
×
UNCOV
460
                    angspan[0] = fmin(angspan[0], 2.*M_PI);     //limit to circumference 
×
UNCOV
461
                    angspan[1] = D->d_proj/M_PI*adjmult;    //zenithal span
×
UNCOV
462
                    rec_hash.add_object( (void*)D->el_addr,  D->az, D->zen, angspan);     
×
463
                }
UNCOV
464
                time("Adding polar mesh neighbors:\t",&fout);
×
465
                //associate neighbors with each zone
UNCOV
466
                rec_hash.add_neighborhood_data(); 
×
467
            }
UNCOV
468
        }
×
469

470
//#define WRITE_NODE_FILE
471
#ifdef WRITE_NODE_FILE
472
        {
473
        //Write out to a file for debugging
474
        ofstream fout2("C:\\Users\\mwagner\\Documents\\NREL\\Dev\\SolTraceWX\\meshxy.txt");
475
        fout2.clear();
476

477
        fout2 << "node,xmin,xmax,ymin,ymax\n";
478

479
        vector<st_opt_element>* all_nodes = sun_hash.get_all_nodes();
480
        for(int i=0; i<all_nodes->size(); i++)
481
        {
482
            double* xr = all_nodes->at(i).get_xr();
483
            double* yr = all_nodes->at(i).get_yr();
484

485
            fout2 << all_nodes->at(i).get_address() << "," << xr[0] << "," << xr[1] << "," << yr[0] << "," << yr[1] << "\n";
486
        }
487

488
        fout2.close();
489

490
        ofstream fout3("C:\\Users\\mwagner\\Documents\\NREL\\Dev\\SolTraceWX\\meshpolar.txt");
491
        fout3.clear();
492

493
        fout3 << "node,xmin,xmax,ymin,ymax\n";
494

495
        all_nodes = rec_hash.get_all_nodes();
496
        for(int i=0; i<all_nodes->size(); i++)
497
        {
498
            double* xr = all_nodes->at(i).get_xr();
499
            double* yr = all_nodes->at(i).get_yr();
500

501
            fout3 << all_nodes->at(i).get_address() << "," << xr[0] << "," << xr[1] << "," << yr[0] << "," << yr[1] << "\n";
502
        }
503

504
        fout3.close();
505
        }
506
#endif
507

508

509
        //declare items used within the loop
510
        vector<void*> sunint_elements;
2✔
511
        vector<void*> reflint_elements;
2✔
512
        bool has_elements;
513

514
        time("Starting stage calculations:\t", &fout);
1✔
515
#ifdef WITH_DEBUG_TIMER
516
        fout.close();
517
#endif
518

519
        //use the callbacks based on elapsed time rather than fixed rays processed. 
520

521
        clock_t startTime = clock();     //start timer
1✔
522
        int rays_per_callback_estimate = 50;    //starting rough estimate for how often to check the clock
1✔
523

524
                for (st_uint_t i=0;i<System->StageList.size();i++)
5✔
525
                {
526

527
                        if (i > 0 && PreviousStageHasRays == false)
4✔
528
                        {
529
                                // no rays to pass through from previous stage
530
                                // so nothing to trace in this stage
531
                                goto Label_EndStageLoop;
×
532
                        }
533
            
534
                        Stage = System->StageList[i];
4✔
535

536
                        LastElementNumber = 0;
4✔
537
                        LastRayNumber = 0;
4✔
538
                        LastHitBackSide = 0;
4✔
539

540
                        StageDataArrayIndex = 0;
4✔
541
                        PreviousStageDataArrayIndex = 0;
4✔
542

543

544
            //if loading stage 0 data, construct appropriate arrays here
545
            if(i==0 && load_st_data)
4✔
546
            {
547
                double rpos[3],rcos[3];
548
                //Stage 0 data
549
                for(int j=0; j<st0data->size(); j++)   
×
550
                {
551
                    
552
                    LoadExistingStage0Ray(j, st0data, 
×
553
                        rpos, rcos,
554
                        LastElementNumber, LastRayNumber);
555

556

557
                    p_ray = Stage->RayData.Append( 
×
558
                        rpos, rcos,
559
                                                LastElementNumber, 1,
560
                                                LastRayNumber );
561

562
                }
563

564
                //stage 1 data
565
                for(int j=0; j<st1in->size(); j++)
×
566
                {
567
                    int rnum;
568
                    LoadExistingStage1Ray(j, st1in, rpos, rcos, rnum);
×
569
                    CopyVec3(IncomingRays[j].Pos, rpos);
×
570
                    CopyVec3(IncomingRays[j].Cos, rcos);
×
571
                    IncomingRays[j].Num = rnum;
×
572
                }
573

574
                PreviousStageHasRays = true;
×
575
                PreviousStageDataArrayIndex = st1in->size()-1;
×
576
                System->SunRayCount = LastRayNumber;
×
577
                goto Label_EndStageLoop;
×
578
            }
579
            
580

581
            
582
Label_StartRayLoop:
42,726✔
583
                        MultipleHitCount = 0;
42,726✔
584
            sunint_elements.clear();
42,726✔
585

586
            has_elements = true;
42,726✔
587
                        if ( i == 0 )
42,726✔
588
                        {
589

590

591
                // we are in the first stage, so 
592
                                // generate a new sun ray in global coords
593
                double PosRaySun[3];
594
                                GenerateRay(myrng, PosSunStage, Stage->Origin,
12,726✔
595
                                                        Stage->RLocToRef, &System->Sun,
12,726✔
596
                                                        PosRayGlob, CosRayGlob, PosRaySun);
597
                                    System->SunRayCount++;
12,726✔
598

599

600
                                if (System->SunRayCount > MaxNumberOfRays)
12,726✔
601
                                {
602
                                        System->errlog("generated sun rays reached maximum count: %d", MaxNumberOfRays);
×
603
                                        return false;
×
604
                                }
605

606
                /* 
607
                Find the list of elements that could potentially interact with this ray. If empty, continue
608
                */
609
                if(! PT_override) //AsPowerTower)
12,726✔
UNCOV
610
                    has_elements = sun_hash.get_all_data_at_loc( sunint_elements, PosRaySun[0], PosRaySun[1] );
×
611

612
                        }
613
                        else
614
                        {
615
                                // we are in a subsequent stage, so trace using an incoming ray
616
                                // saved from the previous stages
617
                RayNumber = IncomingRays[StageDataArrayIndex].Num;
30,000✔
618
                                CopyVec3( PosRayGlob, IncomingRays[StageDataArrayIndex].Pos );
30,000✔
619
                                CopyVec3( CosRayGlob, IncomingRays[StageDataArrayIndex].Cos );
30,000✔
620
                                StageDataArrayIndex++;
30,000✔
621
                                
622
                        }
623

624
                        // transform the global incoming ray to local stage coordinates
625
                        TransformToLocal(PosRayGlob, CosRayGlob, 
42,726✔
626
                                Stage->Origin, Stage->RRefToLoc, 
42,726✔
627
                                PosRayStage, CosRayStage);
628

629

630
                        // CheckForCancelAndUpdateProgressBar
631
                        if (callback != 0
42,726✔
632
                                && RaysTracedTotal++ % rays_per_callback_estimate == 0)
42,726✔
633
                        {
634
                if( RaysTracedTotal > 1 )
2✔
635
                {
636
                    //update how often to call this
637
                    double msec_per_ray = 1000.*( clock() - startTime ) / CLOCKS_PER_SEC / (double)(RaysTracedTotal > 0 ? RaysTracedTotal : 1);
1✔
638
                    //set the new callback estimate to be about 50 ms
639
                    rays_per_callback_estimate = (int)( 200. / msec_per_ray );
1✔
640
                    //limit to something reasonable
641
                    rays_per_callback_estimate = rays_per_callback_estimate < 5 ? 5 : rays_per_callback_estimate;
1✔
642
                }
643

644
                //do the callback
645
                                if ( ! (*callback)( RaysTracedTotal, RayNumber,
2✔
646
                                                                        LastRayNumberInPreviousStage, i+1,
647
                                                                        System->StageList.size(), cbdata ))
648
                                        return true;
×
649
                        }
650
            
651
            in_multi_hit_loop = false;
42,726✔
652
            
653
Label_MultiHitLoop:
82,726✔
654
                        LastPathLength = 1e99;
82,726✔
655
                        StageHit = false;
82,726✔
656

657
            st_uint_t nintelements;
658
            if( i==0 && !PT_override)
82,726✔
659
            {
UNCOV
660
                if( in_multi_hit_loop )
×
661
                {
UNCOV
662
                    if( AsPowerTower )
×
663
                    {
664
                        //>=Second time through - checking for first stage multiple element interactions
665
                    
666
                        //get ray position in receiver polar coordinates
667
                        double raypvec[3];
UNCOV
668
                        for(int jj=0; jj<3; jj++)
×
UNCOV
669
                            raypvec[jj] = PosRayStage[jj] - reccm_helio[jj];
×
UNCOV
670
                        double raypvecmag = sqrt(raypvec[0]*raypvec[0] + raypvec[1]*raypvec[1] + raypvec[2]*raypvec[2]);
×
671
                        double raypol[2];
UNCOV
672
                        raypol[0] = atan2(raypvec[0], raypvec[1]);
×
UNCOV
673
                        raypol[1] = asin(raypvec[2]/raypvecmag);
×
674
                        //get elements in the vicinity of the ray's polar coordinates
UNCOV
675
                        reflint_elements.clear();
×
UNCOV
676
                        rec_hash.get_all_data_at_loc( reflint_elements, raypol[0], raypol[1]);
×
UNCOV
677
                        nintelements = reflint_elements.size();
×
UNCOV
678
                        has_elements = nintelements > 0;
×
679

680
                    }
681
                    else
682
                    {
UNCOV
683
                        nintelements = Stage->ElementList.size();
×
684
                    }
685
                }
686
                else
687
                {
688
                    //First time through - checking for sun ray intersections
UNCOV
689
                    if( has_elements )
×
UNCOV
690
                        nintelements = sunint_elements.size();
×
691
                    else
UNCOV
692
                        nintelements = 0;
×
693
                }
UNCOV
694
            }
×
695
            else
696
                nintelements = Stage->ElementList.size();
82,726✔
697

698
            for( st_uint_t j=0; j<nintelements; j++)
165,452✔
699
                        {
700
                TElement *Element; // = Stage->ElementList[j];
701
                if( i == 0 && !PT_override )
82,726✔
702
                {
UNCOV
703
                    if( in_multi_hit_loop )
×
704
                    {
UNCOV
705
                        if( AsPowerTower )
×
UNCOV
706
                            Element = (TElement*)reflint_elements.at(j);
×
707
                        else
UNCOV
708
                            Element = (TElement*)Stage->ElementList[j];
×
709
                    }
710
                    else
UNCOV
711
                        Element = (TElement*)sunint_elements.at(j);
×
712
                }
713
                else
714
                                    Element = Stage->ElementList[j];
82,726✔
715

716
                                if (!Element->Enabled)
82,726✔
717
                                        continue;
×
718

719
                                //  {Transform ray to element[j] coord system of Stage[i]}
720
                                TransformToLocal( PosRayStage, CosRayStage,
82,726✔
721
                                                                  Element->Origin, Element->RRefToLoc,
82,726✔
722
                                                                  PosRayElement, CosRayElement);
723

724
                                ErrorFlag = 0;
82,726✔
725
                                HitBackSide = 0;
82,726✔
726
                                InterceptFlag = 0;
82,726✔
727

728
                                // increment position by tiny amount to get off the element if tracing to the same element
729
                                PosRayElement[0] = PosRayElement[0] + 1.0e-5*CosRayElement[0];
82,726✔
730
                                PosRayElement[1] = PosRayElement[1] + 1.0e-5*CosRayElement[1];
82,726✔
731
                                PosRayElement[2] = PosRayElement[2] + 1.0e-5*CosRayElement[2];
82,726✔
732

733
                                // {Determine if ray intersects element[j]; if so, Find intersection point with surface of element[j] }
734
                                DetermineElementIntersectionNew(Element, PosRayElement, CosRayElement,
82,726✔
735
                                        PosRaySurfElement, CosRaySurfElement, DFXYZ, 
736
                                        &PathLength, &ErrorFlag, &InterceptFlag, &HitBackSide);
737

738

739

740
                                if (InterceptFlag)
82,726✔
741
                                {
742
                                  //{If hit multiple elements, this loop determines which one hit first.
743
                                  //Also makes sure that correct part of closed surface is hit. Also, handles wavy, but close to flat zernikes and polynomials correctly.}
744
                                  //if (PathLength < LastPathLength) and (PosRaySurfElement[2] <= Element->ZAperture) then
745
                                        if (PathLength < LastPathLength)
40,000✔
746
                                        {
747
                                                if (PosRaySurfElement[2] <= Element->ZAperture 
40,000✔
748
                                                        || Element->SurfaceIndex == 'm'
×
749
                                                        || Element->SurfaceIndex == 'M'
×
750
                                                        || Element->SurfaceIndex == 'r'
×
751
                                                        || Element->SurfaceIndex == 'R') 
×
752
                                                {
753
                                                        StageHit = true;
40,000✔
754
                                                        LastPathLength = PathLength;
40,000✔
755
                                                        CopyVec3( LastPosRaySurfElement, PosRaySurfElement );
40,000✔
756
                                                        CopyVec3( LastCosRaySurfElement, CosRaySurfElement );
40,000✔
757
                                                        CopyVec3( LastDFXYZ, DFXYZ );
40,000✔
758
                                                        LastElementNumber = ( i == 0 && !PT_override )? Element->element_number : j+1;    //mjw change from j index to element id
40,000✔
759
                                                        LastRayNumber = RayNumber;
40,000✔
760
                                                        TransformToReference(PosRaySurfElement, CosRaySurfElement, 
40,000✔
761
                                                                Element->Origin, Element->RLocToRef, 
40,000✔
762
                                                                PosRaySurfStage, CosRaySurfStage);
763

764
                                                        CopyVec3( LastPosRaySurfStage, PosRaySurfStage );
40,000✔
765
                                                        CopyVec3( LastCosRaySurfStage, CosRaySurfStage );
40,000✔
766
                                                        LastHitBackSide = HitBackSide;
40,000✔
767
                                                }
768
                                        }
769
                                }                        
770
                        }
771

772
                        //  {Logic for ray which misses stage element - Note that all rays eventually satisfy this
773
                        //  condition because rays are continually traced until they no longer hit the stage}
774
Label_StageHitLogic:
82,726✔
775

776
                        if ( !StageHit )
82,726✔
777
                        {
778
                                if ( i == 0 ) // first stage only
42,726✔
779
                                {
780
                                        if (MultipleHitCount == 0)
12,726✔
781
                                                goto Label_StartRayLoop; // ray misses 1st stage completely so get a new sun ray
2,726✔
782
                                        else
783
                                        {
784

785
                                                // at least one hit on stage, so move on to next ray
786
                                                CopyVec3( IncomingRays[PreviousStageDataArrayIndex].Pos, PosRayGlob );
10,000✔
787
                                                CopyVec3( IncomingRays[PreviousStageDataArrayIndex].Cos, CosRayGlob );
10,000✔
788
                                                IncomingRays[PreviousStageDataArrayIndex].Num = RayNumber;
10,000✔
789

790
                                                if (RayNumber == NumberOfRays)
10,000✔
791
                                                        goto Label_EndStageLoop;
1✔
792

793
                                                PreviousStageDataArrayIndex++;
9,999✔
794
                                                PreviousStageHasRays = true;
9,999✔
795

796
                                                RayNumber++;
9,999✔
797
                                                goto Label_StartRayLoop;
9,999✔
798
                                        } 
799
                                }
800
                                else
801
                                {
802
                                        // stages beyond first stage
803
                                        if (Stage->TraceThrough || MultipleHitCount > 0)
30,000✔
804
                                        {
805

806
                                                CopyVec3( IncomingRays[PreviousStageDataArrayIndex].Pos, PosRayGlob );
30,000✔
807
                                                CopyVec3( IncomingRays[PreviousStageDataArrayIndex].Cos, CosRayGlob );
30,000✔
808
                                                IncomingRays[PreviousStageDataArrayIndex].Num = RayNumber;
30,000✔
809

810
                                                if (RayNumber == LastRayNumberInPreviousStage)
30,000✔
811
                                                        goto Label_EndStageLoop;
3✔
812

813
                                                PreviousStageDataArrayIndex++;
29,997✔
814
                                                PreviousStageHasRays = true;
29,997✔
815

816
                                                if (MultipleHitCount == 0)
29,997✔
817
                                                        goto Label_FlagMiss;
×
818

819
                                                goto Label_StartRayLoop;
29,997✔
820
                                        }
UNCOV
821
Label_FlagMiss:
×
UNCOV
822
                                        LastElementNumber = 0;
×
UNCOV
823
                                        LastRayNumber = RayNumber;
×
UNCOV
824
                                        CopyVec3(LastPosRaySurfStage, PosRayStage);
×
UNCOV
825
                                        CopyVec3(LastCosRaySurfStage, CosRayStage);
×
826
                                }
827
                        } // end of not stagehit logic
828

829
                        p_ray = Stage->RayData.Append( LastPosRaySurfStage,
80,000✔
830
                                                                  LastCosRaySurfStage,
831
                                                                  LastElementNumber,
832
                                                                  i+1,
40,000✔
833
                                                                  LastRayNumber );
834

835
                        if (!p_ray)
40,000✔
836
                        {
837
                                System->errlog("Failed to save ray data at index %d", Stage->RayData.Count()-1);
×
838
                                return false;
×
839
                        }
840

841
                        if (LastElementNumber == 0) // {If missed all elements}
40,000✔
842
                        {
UNCOV
843
                                if (RayNumber == LastRayNumberInPreviousStage)
×
844
                                {
UNCOV
845
                                        if ( !Stage->TraceThrough )
×
846
                                        {
UNCOV
847
                                                PreviousStageHasRays = false;
×
UNCOV
848
                                                if (PreviousStageDataArrayIndex > 0)
×
849
                                                {
UNCOV
850
                                                        PreviousStageHasRays = true;
×
UNCOV
851
                                                        PreviousStageDataArrayIndex--; // last ray was previous one
×
852
                                                }
853
                                        }
UNCOV
854
                                        goto Label_EndStageLoop;
×
855
                                }
856
                                else
857
                                {
UNCOV
858
                                        if (i == 0) RayNumber++; // generate new sun ray
×
UNCOV
859
                                        goto Label_StartRayLoop;
×
860
                                }
861
                        }
862

863
                        MultipleHitCount++;
40,000✔
864

865
                        if ( Stage->Virtual )
40,000✔
866
                        {
867
                                CopyVec3(PosRayOutElement, LastPosRaySurfElement);
30,000✔
868
                                CopyVec3(CosRayOutElement, LastCosRaySurfElement);
30,000✔
869
                                goto Label_TransformBackToGlobal;
30,000✔
870
                        }
871

872
                        // {Otherwise trace ray through interaction}
873
                        // {Determine if backside or frontside properties should be used}
874
                
875
                        // trace through the interaction
876
                        optelm = Stage->ElementList[ p_ray->element - 1 ];
10,000✔
877
                        optics = 0;
10,000✔
878
                        
879
                        if (LastHitBackSide)
10,000✔
UNCOV
880
                                optics = &optelm->Optics->Back;
×
881
                        else
882
                                optics = &optelm->Optics->Front;
10,000✔
883

884

885
                        double TestValue;
886
                        switch(optelm->InteractionType )
10,000✔
887
                        {
888
                        case 1: // refraction
×
889
                                if (optics->UseTransmissivityTable)
×
890
                                {
891
                                        int npoints = optics->TransmissivityTable.size();
×
892
                                        int m = 0;
×
893
                                        UnitLastDFXYZ[0] = -LastDFXYZ[0] / sqrt(DOT(LastDFXYZ, LastDFXYZ));
×
894
                                        UnitLastDFXYZ[1] = -LastDFXYZ[1] / sqrt(DOT(LastDFXYZ, LastDFXYZ));
×
895
                                        UnitLastDFXYZ[2] = -LastDFXYZ[2] / sqrt(DOT(LastDFXYZ, LastDFXYZ));
×
896
                                        IncidentAngle = acos(DOT(LastCosRaySurfElement, UnitLastDFXYZ))*1000.;  //[mrad]
×
897
                                        if (IncidentAngle >= optics->TransmissivityTable[npoints - 1].angle)
×
898
                                        {
899
                                                TestValue = optics->TransmissivityTable[npoints - 1].trans;
×
900
                                        }
901
                                        else
902
                                        {
903
                                                while (optics->TransmissivityTable[m].angle < IncidentAngle)
×
904
                                                        m++;
×
905

906
                                                if (m == 0)
×
907
                                                        TestValue = optics->TransmissivityTable[m].trans;
×
908
                                                else
909
                                                        TestValue = (optics->TransmissivityTable[m].trans + optics->TransmissivityTable[m - 1].trans) / 2.0;
×
910
                                        }
911
                                }
912
                                else
913
                                        TestValue = optics->Transmissivity; 
×
914
                                break;
×
915
                        case 2: // reflection
10,000✔
916

917
                                if ( optics->UseReflectivityTable )
10,000✔
918
                                {
919
                                        int npoints = optics->ReflectivityTable.size();
×
920
                                        int m = 0;
×
921
                                        UnitLastDFXYZ[0] = -LastDFXYZ[0]/sqrt(DOT(LastDFXYZ,LastDFXYZ));
×
922
                                        UnitLastDFXYZ[1] = -LastDFXYZ[1]/sqrt(DOT(LastDFXYZ,LastDFXYZ));
×
923
                                        UnitLastDFXYZ[2] = -LastDFXYZ[2]/sqrt(DOT(LastDFXYZ,LastDFXYZ));
×
924
                                        IncidentAngle = acos(DOT(LastCosRaySurfElement,UnitLastDFXYZ)) * 1000.;  //[mrad]
×
925
                                        if (IncidentAngle >= optics->ReflectivityTable[ npoints-1 ].angle )
×
926
                                        {
927
                                                TestValue = optics->ReflectivityTable[ npoints-1 ].refl;
×
928
                                        }
929
                                        else
930
                                        {
931
                                                while ( optics->ReflectivityTable[m].angle < IncidentAngle )
×
932
                                                        m++;
×
933

934
                                                if (m == 0)
×
935
                                                        TestValue = optics->ReflectivityTable[m].refl;
×
936
                                                else
937
                                                        TestValue = (optics->ReflectivityTable[m].refl + optics->ReflectivityTable[m-1].refl)/2.0;
×
938
                                        }
939
                                }
940
                                else
941
                                        TestValue = optics->Reflectivity;
10,000✔
942
                                break;
10,000✔
943
                        default:
×
944
                                System->errlog("Bad optical interaction type = %d (stage %d)",i,optelm->InteractionType);
×
945
                                return false;
×
946
                        }
947

948

949
                //  {Apply MonteCarlo probability of absorption. Limited for now, but can make more complex later on if desired}
950
                        if (TestValue <= myrng())
10,000✔
951
                        {
952
                                // ray was fully absorbed, so indicate by negating the element number
UNCOV
953
                                p_ray->element = 0 - p_ray->element;
×
954

UNCOV
955
                                if (RayNumber == LastRayNumberInPreviousStage)
×
956
                                {
UNCOV
957
                                        PreviousStageHasRays = false;
×
UNCOV
958
                                        if (PreviousStageDataArrayIndex > 0)
×
959
                                        {
UNCOV
960
                                                PreviousStageDataArrayIndex--;
×
UNCOV
961
                                                PreviousStageHasRays = true;
×
962
                                        }
UNCOV
963
                                        goto Label_EndStageLoop;
×
964
                                }
965
                                else
966
                                {
UNCOV
967
                                        if (i == 0)
×
968
                                        {
UNCOV
969
                                                if (RayNumber == NumberOfRays)
×
970
                                                        goto Label_EndStageLoop;
×
971
                                                else
UNCOV
972
                                                        RayNumber++;
×
973
                                        }
974

UNCOV
975
                                        goto Label_StartRayLoop;
×
976
                                }
977
                        }
978

979
Label_TransformBackToGlobal:
10,000✔
980
                        k = abs( p_ray->element ) - 1;
40,000✔
981

982
                        if ( !Stage->Virtual )
40,000✔
983
                        {
984
                                if (IncludeSunShape && i == 0 && MultipleHitCount == 1)//change to account for first hit only in primary stage 8-11-31
10,000✔
985
                                {
986
                                        // Apply sunshape to UNPERTURBED ray at intersection point
987
                                        //only apply sunshape error once for primary stage
988
                                        CopyVec3(CosIn, LastCosRaySurfElement);
×
989
                                        Errors(myrng, CosIn, 1, &System->Sun,
×
990
                                                   Stage->ElementList[k], optics, CosOut, LastDFXYZ);  //sun shape
×
991
                                        CopyVec3(LastCosRaySurfElement, CosOut);
×
992
                                }
993

994
                                //{Determine interaction at surface and direction of perturbed ray}
995
                                ErrorFlag = 0;
10,000✔
996

997
                                // {Apply surface normal errors to surface normal before interaction ray at intersection point - Wendelin 11-23-09}
998
                                if( IncludeErrors )
10,000✔
999
                                {
1000
                                        CopyVec3( CosIn, CosRayOutElement );
×
1001
                                        SurfaceNormalErrors(myrng, LastDFXYZ, optics, CosOut);  //surface normal errors
×
1002
                                        CopyVec3( LastDFXYZ, CosOut );
×
1003
                                }
1004

1005
                                Interaction( myrng, LastPosRaySurfElement, LastCosRaySurfElement, LastDFXYZ,
10,000✔
1006
                                        Stage->ElementList[k]->InteractionType, optics, 630.0, 
10,000✔
1007
                                        PosRayOutElement, CosRayOutElement, &ErrorFlag);
1008

1009
                                // {Apply specularity optical error to PERTURBED (i.e. after interaction) ray at intersection point}
1010
                                if( IncludeErrors )
10,000✔
1011
                                {
1012
                                        if (optics->DistributionType == 'F' || optics->DistributionType == 'f')
×
1013
                                                CopyVec3(CosIn, LastDFXYZ);  // Apply diffuse errors relative to surface normal
×
1014
                                        else
1015
                                                CopyVec3(CosIn, CosRayOutElement); // Apply all other errors relative to the specularly-reflected direction
×
1016

1017
                                        Errors(myrng, CosIn, 2, &System->Sun,
×
1018
                                                   Stage->ElementList[k], optics, CosOut, LastDFXYZ);  //optical errors
×
1019
                                        CopyVec3(CosRayOutElement, CosOut);
×
1020
                                }
1021
                        }
1022

1023
                        // { Transform ray back to stage coord system and trace through stage again}
1024
                        TransformToReference(PosRayOutElement, CosRayOutElement, 
40,000✔
1025
                                        Stage->ElementList[k]->Origin, Stage->ElementList[k]->RLocToRef, 
40,000✔
1026
                                        PosRayStage, CosRayStage);
1027
                        TransformToReference(PosRayStage, CosRayStage, 
40,000✔
1028
                                        Stage->Origin, Stage->RLocToRef, 
40,000✔
1029
                                        PosRayGlob, CosRayGlob);
1030

1031
                        if (!Stage->MultiHitsPerRay)
40,000✔
1032
                        {
UNCOV
1033
                                StageHit = false;
×
UNCOV
1034
                                goto Label_StageHitLogic;
×
1035
                        }
1036
                        else
1037
            {
1038
                in_multi_hit_loop = true;
40,000✔
1039
                                goto Label_MultiHitLoop;
40,000✔
1040
            }
1041

1042
Label_EndStageLoop:
4✔
1043

1044
                        if(i==0 && save_st_data)
4✔
1045
            {
1046
                //if flagged save the stage 0 incoming rays data
1047
                TRayData *raydat = &Stage->RayData;
×
1048
                st_uint_t nray0 = raydat->Count();
×
1049
        
1050
                for(st_uint_t ii=0; ii<nray0; ii++)
×
1051
                {
1052
                    TRayData::ray_t *rr = raydat->Index(ii,false);
×
1053

1054
                    std::vector<double> ray(8);
×
1055
                    for(int j=0; j<3; j++)
×
1056
                        ray[j] = rr->pos[j];
×
1057
                    for(int j=0; j<3; j++)
×
1058
                        ray[j+3] = rr->cos[j];
×
1059
                    ray[6] = rr->element;
×
1060
                    ray[7] = rr->raynum;
×
1061
                    st0data->push_back(ray);
×
1062
                }
×
1063
            }
1064

1065
            if(i==1 && save_st_data)
4✔
1066
            {
1067
                //if flagged, save the stage 1 incoming rays data to the data structure passed into the algorithm
1068
                for(int ir=0; ir<StageDataArrayIndex; ir++)
×
1069
                {
1070
                    st1in->push_back(std::vector<double>(7));
×
1071
                    for(int jr=0; jr<3; jr++)
×
1072
                    {
1073
                        st1in->back().at(jr) = IncomingRays[ir].Pos[jr];
×
1074
                        st1in->back().at(jr+3) = IncomingRays[ir].Cos[jr];
×
1075
                    }
1076
                    st1in->back().at(6) = IncomingRays[ir].Num;
×
1077
                }
1078
            }
1079
            
1080

1081
            if (!PreviousStageHasRays)
4✔
1082
                        {
UNCOV
1083
                                LastRayNumberInPreviousStage = 0;
×
UNCOV
1084
                                continue; // no rays to carry forward
×
1085
                        }
1086

1087
                        if (PreviousStageDataArrayIndex < IncomingRays.size())
4✔
1088
                        {
1089
                                LastRayNumberInPreviousStage = IncomingRays[PreviousStageDataArrayIndex].Num;
4✔
1090
                                if (LastRayNumberInPreviousStage == 0)
4✔
1091
                                {
1092
                                        size_t pp = IncomingRays[PreviousStageDataArrayIndex-1].Num;
×
1093
                                        System->errlog("LastRayNumberInPreviousStage=0, stage %d, PrevIdx=%d, CurIdx=%d, pp=%d", i+1,
×
1094
                                                                                PreviousStageDataArrayIndex, StageDataArrayIndex, pp);
1095
                                        return false;
×
1096
                                }
1097
                        }
1098
                        else
1099
                        {
1100
                                System->errlog("Invalid PreviousStageDataArrayIndex: %u, @ stage %d",
×
1101
                                                           PreviousStageDataArrayIndex, i+1);
1102
                                return false;
×
1103
                        }
1104
                }
1105

1106
                return true;
1✔
1107
        }
1✔
1108
        catch( const std::exception &e )
×
1109
        {
1110
                System->errlog("trace error: %s", e.what());
×
1111
                return false;
×
1112
        }
×
1113
}
1✔
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