• 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

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