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

NREL / SolTrace / 18983618523

31 Oct 2025 07:51PM UTC coverage: 89.643% (-0.3%) from 89.946%
18983618523

Pull #75

github

web-flow
Merge e1cafa795 into f6f121007
Pull Request #75: New sun models

120 of 147 new or added lines in 8 files covered. (81.63%)

5 existing lines in 2 files now uncovered.

4423 of 4934 relevant lines covered (89.64%)

9111326.33 hits per line

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

93.23
/coretrace/simulation_runner/native_runner/native_runner.cpp
1

2
#include "native_runner.hpp"
3

4
#include <exception>
5
#include <map>
6
// #include <algorithm>
7

8
// SimulationData headers
9
#include "composite_element.hpp"
10
#include "element.hpp"
11
#include "simulation_parameters.hpp"
12
#include "simulation_data.hpp"
13
#include "simulation_data_export.hpp"
14

15
// NativeRunner headers
16
#include "native_runner_types.hpp"
17
#include "trace.hpp"
18

19
namespace SolTrace::NativeRunner
20
{
21

22
    NativeRunner::NativeRunner() : SimulationRunner(),
23✔
23
                                   as_power_tower(false),
23✔
24
                                   number_of_threads(1)
23✔
25
    {
26
    }
23✔
27

28
    NativeRunner::~NativeRunner()
23✔
29
    {
30
    }
23✔
31

32
    RunnerStatus NativeRunner::initialize()
22✔
33
    {
34
        return RunnerStatus::SUCCESS;
22✔
35
    }
36

37
    RunnerStatus NativeRunner::setup_simulation(const SimulationData *data)
22✔
38
    {
39

40
        RunnerStatus sts;
41

42
        sts = this->setup_parameters(data);
22✔
43

44
        if (sts == RunnerStatus::SUCCESS)
22✔
45
            sts = this->setup_sun(data);
22✔
46

47
        if (sts == RunnerStatus::SUCCESS)
22✔
48
            sts = this->setup_elements(data);
22✔
49

50
        return sts;
22✔
51
    }
52

53
    RunnerStatus NativeRunner::setup_parameters(const SimulationData *data)
22✔
54
    {
55
        // Get Parameter data
56
        // TODO: Check that these parameters are used as expected
57
        const SimulationParameters &sim_params = data->get_simulation_parameters();
22✔
58
        this->tsys.sim_errors_sunshape = sim_params.include_sun_shape_errors;
22✔
59
        this->tsys.sim_errors_optical = sim_params.include_optical_errors;
22✔
60
        this->tsys.sim_raycount = sim_params.number_of_rays;
22✔
61
        this->tsys.sim_raymax = sim_params.max_number_of_rays;
22✔
62
        this->tsys.seed = sim_params.seed;
22✔
63
        return RunnerStatus::SUCCESS;
22✔
64
    }
65

66
    RunnerStatus NativeRunner::setup_sun(const SimulationData *data)
23✔
67
    {
68
        // TODO: This should throw an error...
69
        // Get RaySource data (this runner assumes there is only the Sun)
70
        assert(data->get_number_of_ray_sources() == 1);
23✔
71

72
        ray_source_ptr sun = data->get_ray_source();
23✔
73
        vector_copy(this->tsys.Sun.Origin, sun->get_position());
23✔
74
        this->tsys.Sun.ShapeIndex = sun->get_shape();
23✔
75

76
        // Set sunshape data
77
        switch (sun->get_shape())
23✔
78
        {
79
        case SunShape::GAUSSIAN:
9✔
80
            this->tsys.Sun.Sigma = sun->get_sigma();
9✔
81
            break;
9✔
82
        case SunShape::PILLBOX:
10✔
83
            this->tsys.Sun.Sigma = sun->get_half_width();
10✔
84
            break;
10✔
85
        case SunShape::LIMBDARKENED:
1✔
86
            this->tsys.Sun.MaxAngle = 4.65; // [mrad]
1✔
87
            this->tsys.Sun.MaxIntensity = 1.0;
1✔
88
            break;
1✔
89
        case SunShape::BUIE_CSR: {
1✔
90
            this->tsys.Sun.MaxAngle = 43.6; // [mrad]
1✔
91
            this->tsys.Sun.MaxIntensity = 1.0;
1✔
92
            double kappa, gamma;
93
            sun->calculate_buie_parameters(kappa, gamma);
1✔
94
            this->tsys.Sun.buie_kappa = kappa;
1✔
95
            this->tsys.Sun.buie_gamma = gamma;
1✔
96
            break;
1✔
97
        }
98
        case SunShape::USER_DEFINED: {
2✔
99
            std::vector<double> angle, intensity;
2✔
100
            sun->get_user_data(angle, intensity);
2✔
101
            int npoints = angle.size();
2✔
102

103
            // Set user data
104
            this->tsys.Sun.MaxAngle = 0;
2✔
105
            this->tsys.Sun.MaxIntensity = 0;
2✔
106

107
            this->tsys.Sun.SunShapeAngle.resize(2 * npoints - 1);
2✔
108
            this->tsys.Sun.SunShapeIntensity.resize(2 * npoints - 1);
2✔
109

110
            for (int i = 0; i < npoints; i++)
38✔
111
            {
112
                this->tsys.Sun.SunShapeAngle[npoints + i - 1] = angle[i];
36✔
113
                this->tsys.Sun.SunShapeIntensity[npoints + i - 1] = intensity[i];
36✔
114

115
                if (angle[i] > this->tsys.Sun.MaxAngle)
36✔
116
                    this->tsys.Sun.MaxAngle = angle[i];
34✔
117
                if (intensity[i] > this->tsys.Sun.MaxIntensity)
36✔
118
                    this->tsys.Sun.MaxIntensity = intensity[i];
2✔
119
            }
120
            // fill negative angle side of array -> I don't think we need this.
121
            //for (int i = 0; i < npoints - 1; i++)
122
            //{
123
            //    this->tsys.Sun.SunShapeAngle[i] = -angle[npoints - i - 1];
124
            //    this->tsys.Sun.SunShapeIntensity[i] = intensity[npoints - i - 1];
125
            //}
126
            break;
2✔
127
        }
2✔
NEW
128
        default:
×
129
            // TODO: add error
NEW
130
            break;
×
131
        }
132

133
        return RunnerStatus::SUCCESS;
23✔
134
    }
23✔
135

136
    RunnerStatus NativeRunner::setup_elements(const SimulationData *data)
22✔
137
    {
138
        // TODO: Improve error messages from this function.
139

140
        RunnerStatus sts = RunnerStatus::SUCCESS;
22✔
141
        auto my_map = std::map<int_fast64_t, tstage_ptr>();
22✔
142
        // int_fast64_t current_stage_id = -1;
143
        tstage_ptr current_stage = nullptr;
22✔
144
        int_fast64_t element_number = 1;
22✔
145
        bool element_found_before_stage = false;
22✔
146

147
        for (auto iter = data->get_const_iterator();
22✔
148
             !data->is_at_end(iter);
8,661✔
149
             ++iter)
8,639✔
150
        {
151
            element_ptr el = iter->second;
8,639✔
152
            if (el->is_enabled() && el->is_stage())
8,639✔
153
            {
154
                tstage_ptr stage = make_tstage(el, this->eparams);
25✔
155
                auto retval = my_map.insert(
25✔
156
                    std::make_pair(el->get_stage(), stage));
50✔
157

158
                // current_stage_id = stage->stage_id;
159

160
                // std::cout << "Created stage " << el->get_stage()
161
                //           << " with " << stage->ElementList.size() << " elements"
162
                //           << std::endl;
163

164
                if (retval.second == false)
25✔
165
                {
166
                    // TODO: Duplicate stage numbers. Need to make an error
167
                    // message.
168
                    sts = RunnerStatus::ERROR;
×
169
                }
170

171
                current_stage = stage;
25✔
172
                element_number = 1;
25✔
173
            }
25✔
174
            else if (el->is_enabled() && el->is_single())
8,614✔
175
            {
176
                if (current_stage == nullptr)
8,366✔
177
                {
178
                    // throw std::runtime_error("No stage to add element to");
179
                    element_found_before_stage = true;
81✔
180
                    continue;
81✔
181
                }
182
                else if (el->get_stage() != current_stage->stage_id)
8,285✔
183
                {
184
                    throw std::runtime_error(
185
                        "Element does not match current stage");
×
186
                }
187

188
                telement_ptr elem = make_telement(iter->second,
16,570✔
189
                                                  element_number,
190
                                                  this->eparams);
8,285✔
191
                ++element_number;
8,285✔
192
                current_stage->ElementList.push_back(elem);
8,285✔
193
            }
8,285✔
194
        }
8,639✔
195

196
        if (my_map.size() != 0 && element_found_before_stage)
22✔
197
        {
198
            throw std::runtime_error("Element found without a stage");
×
199
        }
200

201
        if (my_map.size() == 0)
22✔
202
        {
203
            // No stage elements found in the passed in data. However,
204
            // the runner requires stages. So make a single stage
205
            // and put everything there. Note that the coordinates are
206
            // set to correspond to global coordinates. This is necessary
207
            // so that the element coordinate setup in make_element are
208
            // correct.
209
            int_fast64_t element_number = 1;
9✔
210
            auto stage = make_tstage(this->eparams);
9✔
211
            stage->ElementList.reserve(data->get_number_of_elements());
9✔
212
            for (auto iter = data->get_const_iterator();
9✔
213
                 !data->is_at_end(iter);
97✔
214
                 ++iter)
88✔
215
            {
216
                element_ptr el = iter->second;
88✔
217
                if (el->is_enabled() && el->is_single())
88✔
218
                {
219
                    telement_ptr tel = make_telement(el,
220
                                                     element_number,
221
                                                     this->eparams);
81✔
222
                    stage->ElementList.push_back(tel);
81✔
223
                    ++element_number;
81✔
224
                }
81✔
225
            }
88✔
226
            my_map.insert(std::make_pair(0, stage));
9✔
227
        }
9✔
228

229
        // std::map (according to the documentation) is automatically
230
        // ordered by the keys so inserting into a map will sort the stages
231
        // and we can just transfer the pointers, in order, to the StageList
232
        // simply by pulling them out of the map.
233
        int_fast64_t last_stage_id = -1;
22✔
234
        for (auto iter = my_map.cbegin();
22✔
235
             iter != my_map.cend();
56✔
236
             ++iter)
34✔
237
        {
238
            assert(last_stage_id < iter->first);
34✔
239
            last_stage_id = iter->first;
34✔
240
            this->tsys.StageList.push_back(iter->second);
34✔
241
        }
242

243
        if (sts == RunnerStatus::SUCCESS)
22✔
244
        {
245
            // std::cout << "Setting ZAperture..." << std::endl;
246
            // Compute and set ZAperture field in each element
247
            bool success = set_aperture_planes(&this->tsys);
22✔
248
            sts = success ? RunnerStatus::SUCCESS : RunnerStatus::ERROR;
22✔
249
        }
250

251
        return sts;
22✔
252
    }
22✔
253

254
    RunnerStatus NativeRunner::update_simulation(const SimulationData *data)
×
255
    {
256
        // TODO: Do a more efficient implementation of this?
257
        this->tsys.ClearAll();
×
258
        this->setup_simulation(data);
×
259
        return RunnerStatus::SUCCESS;
×
260
    }
261

262
    RunnerStatus NativeRunner::run_simulation()
22✔
263
    {
264
        bool trace_return = trace_native(
44✔
265
            &this->tsys,
266
            this->tsys.seed,
22✔
267
            this->tsys.sim_raycount,
22✔
268
            this->tsys.sim_raymax,
22✔
269
            this->tsys.sim_errors_sunshape,
22✔
270
            this->tsys.sim_errors_optical,
22✔
271
            this->as_power_tower);
22✔
272

273
        // this->tsys.CollectResults();
274

275
        return trace_return ? RunnerStatus::SUCCESS : RunnerStatus::ERROR;
22✔
276
    }
277

278
    RunnerStatus NativeRunner::report_simulation(SolTrace::Result::SimulationResult *result,
3✔
279
                                                 int level)
280
    {
281
        RunnerStatus retval = RunnerStatus::SUCCESS;
3✔
282

283
        const TSystem *sys = this->get_system();
3✔
284
        // const TRayData ray_data = sys->AllRayData;
285
        const TRayData ray_data = sys->RayData;
3✔
286
        std::map<unsigned int, SolTrace::Result::ray_record_ptr> ray_records;
3✔
287
        std::map<unsigned int, SolTrace::Result::ray_record_ptr>::iterator iter;
3✔
288
        size_t ndata = ray_data.Count();
3✔
289

290
        bool sts;
291
        Vector3d point, cosines;
3✔
292
        int element;
293
        int stage;
294
        unsigned int raynum;
295

296
        telement_ptr el = nullptr;
3✔
297
        element_id elid;
298
        SolTrace::Result::ray_record_ptr rec = nullptr;
3✔
299
        SolTrace::Result::interaction_ptr intr = nullptr;
3✔
300
        SolTrace::Result::RayEvent rev;
301

302
        for (size_t ii = 0; ii < ndata; ++ii)
62,247✔
303
        {
304
            sts = ray_data.Query(ii,
62,244✔
305
                                 point.data,
306
                                 cosines.data,
307
                                 &element,
308
                                 &stage,
309
                                 &raynum,
310
                                 &rev);
311

312
            if (!sts)
62,244✔
313
            {
314
                retval = RunnerStatus::ERROR;
×
315
                break;
×
316
            }
317

318
            // std::cout << "ii: " << ii
319
            //           << "\npoint: " << point
320
            //           << "\ndirection: " << cosines
321
            //           << "\nelement: " << element
322
            //           << "\nstage: " << stage
323
            //           << "\nraynum: " << raynum
324
            //           << "\nevent: " << ray_event_string(rev)
325
            //           << std::endl;
326

327
            iter = ray_records.find(raynum);
62,244✔
328
            if (iter == ray_records.end())
62,244✔
329
            {
330
                rec = SolTrace::Result::make_ray_record(raynum);
20,010✔
331
                result->add_ray_record(rec);
20,010✔
332
                ray_records[raynum] = rec;
20,010✔
333
                assert(rev == SolTrace::Result::RayEvent::CREATE);
20,010✔
334
            }
335
            else
336
            {
337
                rec = iter->second;
42,234✔
338
            }
339

340
            if (element > 0)
62,244✔
341
            {
342
                el = sys->StageList[stage - 1]->ElementList[element - 1];
35,633✔
343
                elid = el->sim_data_id;
35,633✔
344
            }
345
            else
346
            {
347
                elid = element;
26,611✔
348
            }
349

350
            intr = make_interaction_record(elid, rev, point, cosines);
62,244✔
351
            rec->add_interaction_record(intr);
62,244✔
352
        }
353

354
        return RunnerStatus::SUCCESS;
3✔
355
    }
3✔
356

357
    bool NativeRunner::set_aperture_planes(TSystem *tsys)
22✔
358
    {
359
        bool retval;
360

361
        for (auto iter = tsys->StageList.cbegin();
22✔
362
             iter != tsys->StageList.cend();
56✔
363
             ++iter)
34✔
364
        {
365
            retval = this->set_aperture_planes(*iter);
34✔
366
            if (!retval)
34✔
367
                break;
×
368
        }
369

370
        return retval;
22✔
371
    }
372

373
    bool NativeRunner::set_aperture_planes(tstage_ptr stage)
34✔
374
    {
375
        bool retval;
376

377
        for (auto eiter = stage->ElementList.begin();
34✔
378
             eiter != stage->ElementList.end();
8,400✔
379
             ++eiter)
8,366✔
380
        {
381
            retval = aperture_plane(*eiter);
8,366✔
382
            if (!retval)
8,366✔
383
                break;
×
384
        }
385

386
        return retval;
34✔
387
    }
388

389
    bool NativeRunner::aperture_plane(telement_ptr Element)
8,366✔
390
    {
391
        /*{Calculates the aperture plane of the element in element coord system.
392
        Applicable to rotationally symmetric apertures surfaces with small
393
        curvature: g, s, p, o, c, v, m, e, r, i.
394
          input - Element = Element record containing geometry of element
395
          output -
396
                 - Element.ZAperture  where ZAperture is the distance from
397
                   the origin to the plane.
398
        }*/
399

400
        Element->ZAperture =
16,732✔
401
            Element->icalc->compute_z_aperture(Element->aperture);
8,366✔
402

403
        return true;
8,366✔
404
    }
405

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