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

NREL / SolTrace / 15936363106

27 Jun 2025 09:31PM UTC coverage: 44.154%. Remained the same
15936363106

push

github

qualand
Merge branch 'develop' of https://github.com/NREL/SolTrace into develop

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

255 existing lines in 5 files now uncovered.

1941 of 4396 relevant lines covered (44.15%)

10000057.35 hits per line

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

75.68
/coretrace/quadricsurfaceclosedform.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
#include <math.h>
52

53
#include "types.h"
54
#include "procs.h"
55

56
#define sqr(x) (x*x)
57

58
void QuadricSurfaceClosedForm(
280,620,704✔
59
                        TElement *Element,
60
                        double PosLoc[3],
61
                        double CosLoc[3],
62
                        double PosXYZ[3],
63
                        double DFXYZ[3],
64
                        double *PathLength,
65
                        int *ErrorFlag)
66
{
67
        double Xdelta = 0.0,Ydelta = 0.0,Zdelta = 0.0;
280,620,704✔
68
        double Xc=0,Yc=0,Zc=0,Kx=0,Ky=0,Kz=0;
280,620,704✔
69
        double r = 0.0,r2 = 0.0,a2=0,b2=0,c2=0;
280,620,704✔
70
        double t1 = 0.0,t2 = 0.0,A=0,B=0,C=0,slopemag = 0.0;
280,620,704✔
71

72
        *ErrorFlag = 0;
280,620,704✔
73

74
        switch( Element->SurfaceIndex )
280,620,704✔
75
        {
76
        case 's':
237,831✔
77
        case 'S': // sphere
78
                        a2 = 1;
237,831✔
79
                        b2 = 1;
237,831✔
80
                        c2 = 1;
237,831✔
81
                        Kx = 1;
237,831✔
82
                        if (Element->SurfaceType == 7)  //Single-axis curvature aperture
237,831✔
83
                                Ky = 0;
×
84
                        else
85
                                Ky = 1;
237,831✔
86
                        Kz = 1;
237,831✔
87
                        r = 1.0/Element->VertexCurvX;
237,831✔
88
                        r2 = r*r;
237,831✔
89
                        Xc = 0.0;
237,831✔
90
                        Yc = 0.0;
237,831✔
91
                        Zc = r;
237,831✔
92
                        
93
                        Xdelta = PosLoc[0] - Xc;
237,831✔
94
                        Ydelta = PosLoc[1] - Yc;
237,831✔
95
                        Zdelta = PosLoc[2] - Zc;
237,831✔
96
                        
97
                        A = CosLoc[0]*CosLoc[0]*Kx/a2 + CosLoc[1]*CosLoc[1]*Ky/b2 + CosLoc[2]*CosLoc[2]*Kz/c2;
237,831✔
98
                        B = 2.0*(Kx*Xdelta*CosLoc[0]/a2 + Ky*Ydelta*CosLoc[1]/b2 + Kz*Zdelta*CosLoc[2]/c2);
237,831✔
99
                        C = Kx*Xdelta*Xdelta/a2 + Ky*Ydelta*Ydelta/b2 + Kz*Zdelta*Zdelta/c2 - r2;
237,831✔
100
                break;
237,831✔
101

102
        case 'p':
280,291,084✔
103
        case 'P':   //parabola
104
                        a2 = 2.0/Element->VertexCurvX;
280,291,084✔
105
                        b2 = Element->VertexCurvY > 0.0 ? 2.0/Element->VertexCurvY : 1e10;
280,291,084✔
106
                        c2 = 1.0;
280,291,084✔
107

108
                        Kx = 1;
280,291,084✔
109
                        if (Element->SurfaceType == 7)  //Single-axis curvature aperture
280,291,084✔
110
                                Ky = 0;
×
111
                        else
112
                                Ky = 1;
280,291,084✔
113
                        Kz = 0;
280,291,084✔
114

115
                        Xc = 0.0;
280,291,084✔
116
                        Yc = 0.0;
280,291,084✔
117
                        Zc = 0.0;
280,291,084✔
118
                        
119
                        Xdelta = PosLoc[0] - Xc;
280,291,084✔
120
                        Ydelta = PosLoc[1] - Yc;
280,291,084✔
121
                        Zdelta = PosLoc[2] - Zc;
280,291,084✔
122

123
                        A = CosLoc[0] * CosLoc[0] * Kx / a2 + CosLoc[1] * CosLoc[1] * Ky / b2;  // Note A can be zero
280,291,084✔
124
                        B = 2.0 * (Kx * Xdelta * CosLoc[0] / a2 + Ky * Ydelta * CosLoc[1] / b2) - CosLoc[2] / c2;
280,291,084✔
125
                        C = Kx * Xdelta * Xdelta / a2 + Ky * Ydelta * Ydelta / b2 - Zdelta / c2;
280,291,084✔
126

127
                break;
280,291,084✔
128
                
129
        case 'o':
×
130
        case 'O':   //other
131
                a2 = 1;
×
132
                b2 = 1;
×
133
                c2 = 1;
×
134
                Kx = 1;
×
135
                Ky = 1;
×
136
                Kz = Element->Kappa;
×
137
                Xc = 0.0;
×
138
                Yc = 0.0;
×
139
                Zc = 1.0/Element->Kappa/Element->VertexCurvX;  // VertexCurvX = VertexCurvY for this surface type
×
140

141
                Xdelta = PosLoc[0] - Xc;
×
142
                Ydelta = PosLoc[1] - Yc;
×
143
                Zdelta = PosLoc[2] - Zc;
×
144

145
                A = CosLoc[0] * CosLoc[0] * Kx / a2 + CosLoc[1] * CosLoc[1] * Ky / b2 + CosLoc[2] * CosLoc[2] * Kz / c2;
×
146
                B = 2.0 * (Kx * Xdelta * CosLoc[0] / a2 + Ky * Ydelta * CosLoc[1] / b2 + Kz * Zdelta * CosLoc[2] / c2);
×
147
                C = Kx * Xdelta * Xdelta / a2 + Ky * Ydelta * Ydelta / b2 + Kz * Zdelta * Zdelta / c2 - 1.0/Element->Kappa/(Element->VertexCurvX * Element->VertexCurvX);
×
148
                break;
×
149

150
        case 't':
91,789✔
151
        case 'T':   //cylinder
152
                        a2 = 1;
91,789✔
153
                        b2 = 1;
91,789✔
154
                        c2 = 1;
91,789✔
155
                        Kx = 1;
91,789✔
156
                        Ky = 0;
91,789✔
157
                        Kz = 1;
91,789✔
158
                        r = 1.0/Element->CurvOfRev;
91,789✔
159
                        r2 = r*r;
91,789✔
160
                        Xc = 0.0;
91,789✔
161
                        Yc = 0.0;
91,789✔
162
                        Zc = r;
91,789✔
163
                        
164
                        Xdelta = PosLoc[0] - Xc;
91,789✔
165
                        Ydelta = PosLoc[1] - Yc;
91,789✔
166
                        Zdelta = PosLoc[2] - Zc;
91,789✔
167
                        
168
                        A = CosLoc[0]*CosLoc[0]*Kx/a2 + CosLoc[1]*CosLoc[1]*Ky/b2 + CosLoc[2]*CosLoc[2]*Kz/c2;
91,789✔
169
                        B = 2.0*(Kx*Xdelta*CosLoc[0]/a2 + Ky*Ydelta*CosLoc[1]/b2 + Kz*Zdelta*CosLoc[2]/c2);
91,789✔
170
                        C = Kx*Xdelta*Xdelta/a2 + Ky*Ydelta*Ydelta/a2 + Kz*Zdelta*Zdelta/c2 - r2;
91,789✔
171
                break;
91,789✔
172

173
        case 'c':
×
174
        case 'C':   //cone
175
                break;
×
176

177
        case 'f':
×
178
        case 'F':   //flat
179
                break;
×
180
        }
181

182
        if (fabs(A) < 1e-12)  // Should only happen for parabolas
280,620,704✔
183
        {
184
                t1 = -C / B;
6✔
185
                if (t1 > 0)
6✔
186
                {
187
                        PosXYZ[0] = PosLoc[0] + t1 * CosLoc[0];
5✔
188
                        PosXYZ[1] = PosLoc[1] + t1 * CosLoc[1];
5✔
189
                        PosXYZ[2] = PosLoc[2] + t1 * CosLoc[2];
5✔
190
                        *PathLength = t1;
5✔
191
                        //goto Label_100;
192
                }
193
                else
194
                {
195
                        *PathLength = 0.0; //ray tangent or missed
1✔
196
                        *ErrorFlag = 1;
1✔
197
                        return;
1✔
198
                }
199
        }
200
        else if (sqr(B) > 4.0*A*C)
280,620,698✔
201
        {
202
                t1 = (-B + sqrt(sqr(B)-4.0*A*C))/(2.0*A);
280,620,688✔
203
                t2 = (-B - sqrt(sqr(B)-4.0*A*C))/(2.0*A);
280,620,688✔
204
                if (t2 > 0)    //initial ray location outside surface
280,620,688✔
205
                {
206
                        PosXYZ[0] = PosLoc[0] + t2*CosLoc[0];
118,729,992✔
207
                        PosXYZ[1] = PosLoc[1] + t2*CosLoc[1];
118,729,992✔
208
                        PosXYZ[2] = PosLoc[2] + t2*CosLoc[2];
118,729,992✔
209
                        *PathLength = t2;
118,729,992✔
210

211
                        //*************************************************************************************************************
212
                        //makes sure to get shortest ray path on valid side of surface; 10-05-10    for open surface of parabola
213
                        //if cylinder, then PosXYZ[3] will always be less than or equal to Element.Zaperture so never passes this test.
214
                        // Test for  cylinder follows below.
215
                        if (PosXYZ[2] > Element->ZAperture)
118,729,992✔
216
                        {
217
                                PosXYZ[0] = PosLoc[0] + t1*CosLoc[0];
118,637,763✔
218
                                PosXYZ[1] = PosLoc[1] + t1*CosLoc[1];
118,637,763✔
219
                                PosXYZ[2] = PosLoc[2] + t1*CosLoc[2];
118,637,763✔
220
                                *PathLength = t1;
118,637,763✔
221
                        }
222

223
                        // Remember at this point, intersection is being found on an INFINITELY long cylinder.
224
                        //if 1st intersection on INFINITELY long cylinder is from the outside, t2, check to make sure
225
                        //intersection is within the finite
226
                        // length of the actual cylinder geometry, if not then 2nd intersection on the inside, t1,
227
                        //is valid one to use.  This means ray could
228
                        // enter from the open end  of the cylinder and hit on the inside.  The final test for this is in the
229
                        //calling routine:  DetermineElementIntersectionNew
230
                        // Wendelin 10-05-10
231
                        if ((Element->SurfaceIndex == 't') || (Element->SurfaceIndex == 'T'))
118,729,992✔
232
                        {
233
                                if ((PosXYZ[1] < -Element->ParameterC/2.0) || (PosXYZ[1] > Element->ParameterC/2.0))
86,437✔
234
                                {
235
                                        PosXYZ[0] = PosLoc[0] + t1*CosLoc[0];
×
UNCOV
236
                                        PosXYZ[1] = PosLoc[1] + t1*CosLoc[1];
×
UNCOV
237
                                        PosXYZ[2] = PosLoc[2] + t1*CosLoc[2];
×
UNCOV
238
                                        *PathLength = t1;
×
239
                                }
240
                        }
241

242
                        // Partial cylinder (sphere with single-axis curvature) needs the same check as cylinder. 
243
                        // Two intersections are possible, check if the first intersection along the ray path occurs within the length bounds and, if not, return the second intersection
244
                        // The final test for a positive ray path and a valid intersection location is in DetermineElementIntersectionNew. If t1 is negative, this intersection location will be ignored in DetermineElementIntersectionNew
245
                        if (((Element->SurfaceIndex == 's') || (Element->SurfaceIndex == 'S')) && (Element->SurfaceType == 7)) 
118,729,992✔
246
                        {
247
                                if ((PosXYZ[1] < -Element->ParameterC / 2.0) || (PosXYZ[1] > Element->ParameterC / 2.0))
×
248
                                {
249
                                        PosXYZ[0] = PosLoc[0] + t1*CosLoc[0];
×
UNCOV
250
                                        PosXYZ[1] = PosLoc[1] + t1*CosLoc[1];
×
UNCOV
251
                                        PosXYZ[2] = PosLoc[2] + t1*CosLoc[2];
×
UNCOV
252
                                        *PathLength = t1;
×
253
                                }
254
                        }
255
           //***********************************************************************************************************
256

257
                        //goto Label_100;
258
                }
259
                else if (t2 == 0)   //initial ray location at surface
161,890,696✔
260
                {
261
                        PosXYZ[0] = PosLoc[0] + t1*CosLoc[0];
×
UNCOV
262
                        PosXYZ[1] = PosLoc[1] + t1*CosLoc[1];
×
UNCOV
263
                        PosXYZ[2] = PosLoc[2] + t1*CosLoc[2];
×
UNCOV
264
                        *PathLength = t1;
×
265
                        //goto Label_100;
266
                }
267
                else if (t2 < 0 && t1 > 0)     //initial ray location inside surface
161,890,696✔
268
                {
269
                        PosXYZ[0] = PosLoc[0] + t1*CosLoc[0];
161,885,349✔
270
                        PosXYZ[1] = PosLoc[1] + t1*CosLoc[1];
161,885,349✔
271
                        PosXYZ[2] = PosLoc[2] + t1*CosLoc[2];
161,885,349✔
272
                        *PathLength = t1;
161,885,349✔
273
                        //goto Label_100;
274
                }
275
                else if (t1 <= 0)
5,347✔
276
                {
277
                        *PathLength = t1; //ray heading away from surface
5,347✔
278
                        *ErrorFlag = 1;
5,347✔
279
                        return;
5,347✔
280
                }
281
        }
282
        else
283
        {
284
                *PathLength = 0.0; //ray tangent or missed
10✔
285
                *ErrorFlag = 1;
10✔
286
                return;
10✔
287
        }
288

289
//Label_100:
290

291
        if (Element->SurfaceIndex == 'p' || Element->SurfaceIndex == 'P')
280,615,346✔
292
        {
293
                slopemag = sqrt(sqr(2.0 * Kx * (PosXYZ[0] - Xc) / a2) + sqr(2.0 * Ky * (PosXYZ[1] - Yc) / b2) + 1.0);
280,291,083✔
294
                DFXYZ[0] = -(2.0 * Kx * (PosXYZ[0] - Xc) / a2) / slopemag;
280,291,083✔
295
                DFXYZ[1] = -(2.0 * Ky * (PosXYZ[1] - Yc) / b2) / slopemag;
280,291,083✔
296
                DFXYZ[2] = 1.0 / slopemag;
280,291,083✔
297
        }
298
        else
299
        {
300
                slopemag = sqrt(sqr(2.0 * Kx * (PosXYZ[0] - Xc) / a2) + sqr(2.0 * Ky * (PosXYZ[1] - Yc) / b2) + sqr(2.0 * Kz * (PosXYZ[2] - Zc) / c2));
324,263✔
301
                DFXYZ[0] = -(2.0 * Kx * (PosXYZ[0] - Xc) / a2) / slopemag;
324,263✔
302
                DFXYZ[1] = -(2.0 * Ky * (PosXYZ[1] - Yc) / b2) / slopemag;
324,263✔
303
                DFXYZ[2] = -(2.0 * Kz * (PosXYZ[2] - Zc) / c2) / slopemag;
324,263✔
304
        }
305
}
306
//end of procedure--------------------------------------------------------------
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