RayZaler 0.1
The free opto-mechanical simulation framework
RayBeam.h
1//
2// Copyright (c) 2024 Gonzalo José Carracedo Carballal
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Lesser General Public License as
6// published by the Free Software Foundation, either version 3 of the
7// License, or (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Lesser General Public License for more details.
13//
14// You should have received a copy of the GNU Lesser General Public
15// License along with this program. If not, see
16// <http://www.gnu.org/licenses/>
17//
18
19
20#ifndef _RAY_BEAM_H
21#define _RAY_BEAM_H
22
23#include <cassert>
24#include <stdint.h>
25#include <vector>
26#include <list>
27#include <map>
28#include <functional>
29
30#include <Vector.h>
31#include "MediumBoundary.h"
32
33#define RZ_BEAM_MINIMUM_WAVELENGTH 1e-12
34
35namespace RZ {
36 class ReferenceFrame;
37 class OpticalSurface;
38
39 struct Ray {
40 // Defined by input
41 Vec3 origin;
42 Vec3 direction;
43
44 // Incremented by tracer
45 Real length = 0;
46 Real cumOptLength = 0;
47
48 // Defines whether the ray is susceptible to vignetting
49 bool chief = false;
50 bool intercepted = false;
51
52 RZ::Real wavelength = RZ_WAVELENGTH;
53 RZ::Real refNdx = 1.; // Refractive index of the medium
54
55 // Defined by the user
56 uint32_t id = 0;
57 };
58
59 class RayList : public std::list<RZ::Ray, std::allocator<RZ::Ray>> { };
60
62 uint64_t intercepted = 0;
63 uint64_t vignetted = 0;
64 uint64_t pruned = 0;
65
66 inline RayBeamStatistics &
67 operator +=(RayBeamStatistics const &existing)
68 {
69 intercepted += existing.intercepted;
70 vignetted += existing.vignetted;
71 pruned += existing.pruned;
72
73 return *this;
74 }
75 };
76
77 enum RayExtractionMask {
78 OriginPOV = 1,
79 DestinationPOV = 2,
80 BeamIsSurfaceRelative = 4,
81 RayShouldBeSurfaceRelative = 8,
82 ExtractIntercepted = 16,
83 ExtractVignetted = 32,
84 ExcludeBeam = 64,
85 ExtractAll = ExtractIntercepted | ExtractVignetted
86 };
87
88 struct RayBeam {
89 uint64_t count = 0;
90 uint64_t allocation = 0;
91 bool nonSeq = false; // Non sequential beam (allocs surfaces)
92
93 Real *origins = nullptr;
94 Real *directions = nullptr;
95 Real *destinations = nullptr;
96 Complex *amplitude = nullptr;
97 Real *lengths = nullptr;
98 Real *cumOptLengths = nullptr;
99 Real *normals = nullptr; // Surface normals of the boundary surface
100 Real *wavelengths = nullptr;
101 Real *refNdx = nullptr;
102
103 uint32_t *ids = nullptr;
104
105 uint64_t *mask = nullptr;
106 uint64_t *intMask = nullptr;
107 uint64_t *prevMask = nullptr;
108 uint64_t *chiefMask = nullptr;
109
110 OpticalSurface **surfaces = nullptr;
111
112 inline bool
113 isChief(uint64_t index) const
114 {
115 return (chiefMask[index >> 6] & (1ull << (index & 63))) >> (index & 63);
116 }
117
118 inline bool
119 isIntercepted(uint64_t index) const
120 {
121 return (intMask[index >> 6] & (1ull << (index & 63))) >> (index & 63);
122 }
123
124 inline bool
125 hasRay(uint64_t index) const
126 {
127 return (~mask[index >> 6] & (1ull << (index & 63))) >> (index & 63);
128 }
129
130 inline void
131 prune(uint64_t c)
132 {
133 if (!isChief(c) && hasRay(c))
134 mask[c >> 6] |= 1ull << (c & 63);
135 }
136
137 inline void
138 pruneAll()
139 {
140 size_t maskSize = ((count + 63) >> 6) << 3;
141 memset(mask, 0xff, maskSize);
142 }
143
144 inline void
145 uninterceptAll()
146 {
147 size_t maskSize = ((count + 63) >> 6) << 3;
148 memset(intMask, 0, maskSize);
149 }
150
151 inline void
152 intercept(uint64_t c)
153 {
154 if (hasRay(c))
155 intMask[c >> 6] |= 1ull << (c & 63);
156 }
157
158 inline bool
159 setChiefRay(uint64_t c)
160 {
161 if (!hasRay(c))
162 return false;
163
164 chiefMask[c >> 6] |= 1ull << (c & 63);
165 return true;
166 }
167
168 inline bool
169 unsetsetChiefRay(uint64_t c)
170 {
171 if (!hasRay(c))
172 return false;
173
174 chiefMask[c >> 6] &= ~(1ull << (c & 63));
175 return true;
176 }
177
178 inline bool
179 hadRay(uint64_t index) const
180 {
181 return (~prevMask[index >> 6] & (1ull << (index & 63))) >> (index & 63);
182 }
183
184 #define SETMASK(field) \
185 field[word] = (field[word] & ~bit) | (existing->field[word] & bit)
186 inline void
187 copyRay(const RayBeam *existing, uint64_t index)
188 {
189 uint64_t bit = 1ull << (index & 63);
190 uint64_t word = index >> 6;
191
192 memcpy(origins + 3 * index, existing->origins + 3 * index, 3 * sizeof(Real));
193 memcpy(directions + 3 * index, existing->directions + 3 * index, 3 * sizeof(Real));
194 memcpy(normals + 3 * index, existing->normals + 3 * index, 3 * sizeof(Real));
195 memcpy(destinations + 3 * index, existing->destinations + 3 * index, 3 * sizeof(Real));
196
197 amplitude[index] = existing->amplitude[index];
198 lengths[index] = existing->lengths[index];
199 cumOptLengths[index] = existing->lengths[index];
200 refNdx[index] = existing->refNdx[index];
201 wavelengths[index] = existing->wavelengths[index];
202 ids[index] = existing->ids[index];
203
204 SETMASK(mask);
205 SETMASK(chiefMask);
206 SETMASK(intMask);
207 SETMASK(prevMask);
208 }
209 #undef SETMASK
210
211 virtual void allocate(uint64_t);
212 virtual void deallocate();
213
214 template <class T> void extractRays(
215 T &dest,
216 uint32_t mask,
217 OpticalSurface *current = nullptr,
218 RayBeamSlice const &beam = RayBeamSlice());
219
220 template <class T> static void extractRays(
221 T &dest,
222 RayBeamSlice const &slice,
223 uint32_t mask,
224 OpticalSurface *current = nullptr,
225 RayBeamSlice const &beam = RayBeamSlice());
226
227
228 void clearMask();
229 void computeInterceptStatistics(OpticalSurface * = nullptr);
230 void updateOrigins();
231
232 //
233 // toRelative and fromRelative only act on:
234 //
235 // - origins
236 // - destinations
237 // - directions
238 //
239 // we leave normals untouched, as we only care about them during
240 // EMInterface calculations
241 //
242 void toRelative(const ReferenceFrame *plane);
243 void toRelative(RayBeam *, const ReferenceFrame *plane) const;
244
245 void fromRelative(const ReferenceFrame *plane);
246 void fromSurfaceRelative();
247
248 void walk(
250 const std::function <void (OpticalSurface *, RayBeamSlice const &)>& f);
251
252 uint64_t updateFromVisible(const OpticalSurface *, const RayBeam *);
253
254 RayBeam(uint64_t, bool mediumBoundaries = false);
255 ~RayBeam();
256
257 private:
258 void addInterceptMetrics(OpticalSurface *surface, RayBeamSlice const &slice);
259 };
260
262 RayBeam *beam = nullptr;
263 uint64_t start = 0;
264 uint64_t end = 0;
265
266 RayBeamSlice(RayBeam *beam, uint64_t start, uint64_t end) : beam(beam) {
267 assert(start <= end);
268 assert(end <= beam->count);
269 assert(start < beam->count);
270
271 this->start = start;
272 this->end = end;
273 }
274
275 RayBeamSlice(RayBeam *beam) : RayBeamSlice(beam, 0, beam->count) { }
276
277 RayBeamSlice() : beam(nullptr), start(0), end(0) { }
278 };
279}
280
281#endif // _RAY_BEAM_H
282
Definition: RayBeam.h:59
Definition: ReferenceFrame.h:59
Definition: OpticalElement.h:33
Definition: RayBeam.h:88
Definition: RayBeam.h:261
Definition: RayBeam.h:61
Definition: RayBeam.h:39
Definition: Vector.h:66