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

NREL / SolTrace / 18984697163

31 Oct 2025 08:41PM UTC coverage: 89.643% (-0.3%) from 89.946%
18984697163

push

github

web-flow
New sun models (#75)

* Refactor sun shape handling to use SunShape enum

Introduces a new SunShape enum to distinguish sun shape types from error distribution types, updating all relevant interfaces, implementations, and tests. This improves clarity and maintainability by separating sun shape logic from error distribution logic, and adds support for diffuse and user-defined sun shapes.

* Add Buie CSR and limb-darkened sun shape models

Introduces support for Buie circumsolar ratio (CSR) and limb-darkened sun shape models in the simulation framework. Updates the Sun class and related interfaces to handle the new parameters, implements error checking for CSR, and extends the native runner and error tracing logic to support these sun shapes. Updates unit and regression tests to cover the new models and their error handling.

* Fix branch syntax in CI workflow

* Improve sun shape error handling and comments

Added explanatory comments for unit conversions and sun model behavior. Improved error handling by throwing an exception for unsupported sun shapes. Minor code cleanup and TODO notes for future improvements.

* Limit CI workflow branches to 'develop'

* fixing pull request issues found by Copilot

* Refactor error calculation and update phi computation

Removed unused variables and replaced hardcoded pi value with PI constant in phi calculation for both SurfaceNormalErrors and Errors functions. Added detailed TODO and notes for future refactoring to reduce code duplication and improve error handling.

* Refactor tower demo tests to use shared setup function

Introduced create_tower_demo_simulation_data(bool) to consolidate simulation data setup for all test cases. Updated all tests to use this function, reducing code duplication and improving maintainability. Sun shape modifications for specific tests are now performed after setup. Minor formatting and pointer type consistency improvements.

* Refactor sun shape handling and add new test cases

Rem... (continued)

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

97.44
/coretrace/simulation_data/sun.cpp
1
#include "sun.hpp"
2

3
#include <algorithm>
4
#include <cmath>
5
#include <limits>
6
#include <stdexcept>
7

8
namespace SolTrace::Data {
9

10
void Sun::set_gaussian_distribution(double _sigma)
17✔
11
{
12
    if (_sigma <= 0.0)
17✔
13
    {
14
        throw std::invalid_argument("Gaussian distribution sigma must be positive");
2✔
15
    }
16
    if (std::isnan(_sigma) || std::isinf(_sigma))
15✔
17
    {
18
        throw std::invalid_argument("Gaussian distribution sigma must be finite");
2✔
19
    }
20

21
    sigma = _sigma;
13✔
22
}
13✔
23

24
void Sun::set_pillbox_distribution(double _half_width)
15✔
25
{
26
    if (_half_width <= 0.0)
15✔
27
    {
28
        throw std::invalid_argument("Pillbox distribution half_width must be positive");
2✔
29
    }
30
    if (std::isnan(_half_width) || std::isinf(_half_width))
13✔
31
    {
32
        throw std::invalid_argument("Pillbox distribution half_width must be finite");
2✔
33
    }
34

35
    half_width = _half_width;
11✔
36
}
11✔
37

38
void Sun::set_buie_csr_distribution(double _csr)
6✔
39
{
40
    if (_csr < 0.0 || _csr > 0.8)
6✔
41
    {
42
        throw std::invalid_argument("Buie CSR must be in the range [0, 0.8]");
3✔
43
    }
44
    if (std::isnan(_csr) || std::isinf(_csr))
3✔
45
    {
46
        throw std::invalid_argument("Buie CSR must be finite");
1✔
47
    }
48
    circumsolar_ratio = _csr;
2✔
49
}
2✔
50

51
void Sun::calculate_buie_parameters(double& kappa, double& gamma)
1✔
52
{
53
    // Calculate kappa and gamma parameters
54
    // Creates the Buie (2003) sun shape based on CSR
55
    // [1] Buie, D., Dey, C., & Bosi, S. (2003). The effective size of the solar cone for solar concentrating systems. Solar energy, 74(2003), 417-427.
56
    // [2] Buie, D., Monger, A., & Dey, C. (2003). Sun shape distributions for terrestrial solar simulations. Solar Energy, 74(March 2003), 113-122.
57
    double csr = this->get_circumsolar_ratio();
1✔
58
    double chi;
59
    if (csr > 0.145)
1✔
NEW
60
        chi = -0.04419909985804843 + csr * (1.401323894233574 + csr * (-0.3639746714505299 + csr * (-0.9579768560161194 + 1.1550475450828657 * csr)));
×
61
    else if (csr > 0.035)
1✔
62
        chi = 0.022652077593662934 + csr * (0.5252380349996234 + (2.5484334534423887 - 0.8763755326550412 * csr) * csr);
1✔
63
    else
NEW
64
        chi = 0.004733749294807862 + csr * (4.716738065192151 + csr * (-463.506669149804 + csr * (24745.88727411664 + csr * (-606122.7511711778 + 5521693.445014727 * csr))));
×
65
    
66
    kappa = 0.9 * log(13.5 * chi) * pow(chi, -0.3);
1✔
67
    gamma = 2.2 * log(0.52 * chi) * pow(chi, 0.43) - 0.1;
1✔
68
}
1✔
69

70
void Sun::set_user_defined_distribution(std::vector<double> _user_angle,
13✔
71
                                        std::vector<double> _user_intensity)
72
{
73
    if (_user_angle.empty())
13✔
74
    {
75
        throw std::invalid_argument("User-defined distribution requires non-empty angle vector");
2✔
76
    }
77
    if (_user_intensity.empty())
11✔
78
    {
79
        throw std::invalid_argument("User-defined distribution requires non-empty intensity vector");
1✔
80
    }
81
    if (_user_angle.size() != _user_intensity.size())
10✔
82
    {
83
        throw std::invalid_argument("User-defined distribution angle and intensity vectors must have same size");
1✔
84
    }
85

86
    // Check for valid angle values
87
    for (const auto &angle : _user_angle)
57✔
88
    {
89
        if (std::isnan(angle) || std::isinf(angle))
50✔
90
        {
91
            throw std::invalid_argument("User-defined distribution angles must be finite");
1✔
92
        }
93
        if (angle < 0.0)
49✔
94
        {
95
            throw std::invalid_argument("User-defined distribution angles must be non-negative");
1✔
96
        }
97
    }
98

99
    // Check for valid intensity values
100
    for (const auto &intensity : _user_intensity)
52✔
101
    {
102
        if (std::isnan(intensity) || std::isinf(intensity))
47✔
103
        {
104
            throw std::invalid_argument("User-defined distribution intensities must be finite");
1✔
105
        }
106
        if (intensity < 0.0)
46✔
107
        {
108
            throw std::invalid_argument("User-defined distribution intensities must be non-negative");
1✔
109
        }
110
    }
111

112
    // Check that angles are in ascending order
113
    if (!std::is_sorted(_user_angle.begin(), _user_angle.end()))
5✔
114
    {
115
        throw std::invalid_argument("User-defined distribution angles must be in ascending order");
1✔
116
    }
117

118
    user_angle = std::move(_user_angle);
4✔
119
    user_intensity = std::move(_user_intensity);
4✔
120
}
4✔
121

122
void Sun::set_shape(SunShape shape,
54✔
123
                    double _sigma,
124
                    double _half_width,
125
                    double _csr,
126
                    std::vector<double> _user_angle,
127
                    std::vector<double> _user_intensity)
128
{
129
    this->my_shape = shape;
54✔
130

131
    // Clear arguments
132
    sigma = std::numeric_limits<double>::quiet_NaN();
54✔
133
    half_width = std::numeric_limits<double>::quiet_NaN();
54✔
134
    circumsolar_ratio = std::numeric_limits<double>::quiet_NaN();
54✔
135
    user_angle.clear();
54✔
136
    user_intensity.clear();
54✔
137

138
    switch (shape)
54✔
139
    {
140
    case (SunShape::GAUSSIAN):
17✔
141
        set_gaussian_distribution(_sigma);
17✔
142
        break;
13✔
143
    case (SunShape::PILLBOX):
15✔
144
        set_pillbox_distribution(_half_width);
15✔
145
        break;
11✔
146
    case (SunShape::LIMBDARKENED):
2✔
147
        break;
2✔
148
    case (SunShape::BUIE_CSR):
6✔
149
        set_buie_csr_distribution(_csr);
6✔
150
        break;
2✔
151
    case (SunShape::USER_DEFINED):
13✔
152
        set_user_defined_distribution(std::move(_user_angle), std::move(_user_intensity));
31✔
153
        break;
4✔
154
    default:
1✔
155
        throw std::invalid_argument("Unknown distribution type");
1✔
156
        break;
157
    }
158

159
    return;
32✔
160
}
161

162
} // namespace SolTrace::Data
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