RayZaler 0.1
The free opto-mechanical simulation framework
OMModel.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#ifndef _OMMODEL_H
20#define _OMMODEL_H
21
22#include <Vector.h>
23#include <WorldFrame.h>
24#include <ReferenceFrame.h>
25#include <Element.h>
26#include <Singleton.h>
27#include <OpticalElement.h>
28#include <Elements/Detector.h>
29#include <Random.h>
30#include <SkySampler.h>
31#include <list>
32#include <map>
33
34#define _STRINGIFY(x) #x
35#define STRINGIFY(x) _STRINGIFY(x)
36
37#define RZ_DEFAULT_CCD_RESOLUTION 1024
38#define RZ_DEFAULT_CCD_WIDTH 5e-2
39#define RZ_WAVELENGTH 555e-9
40
41namespace RZ {
42 class OMModel;
43 class GenericCompositeModel;
44 class Simulation;
45
46 //
47 // An Opto-Mechanical model consists of:
48 //
49 // - A World reference frame
50 // - Some other ancillary reference frames
51 // - Elements, defined on top of other reference frames. Of which
52 // - Some may be detectors
53 // - One or more optical paths
54 // - A set of degrees of freedom (with their defaults)
55 // - A set of parameters (with their defaults)
56 // - A set of conversion rules
57 //
58 // Additionally, compound elements may be defined.
59 //
60
61 class ExpressionEvaluator;
62 class RayBeamElement;
63 class RayColoring;
64
66 Real value;
67 std::string expression;
68 ExpressionEvaluator *evaluator = nullptr;
69 std::list<std::string> change_list;
70 };
71
72
74 OMModel *m_model = nullptr;
75 ReferenceFrame *m_last = nullptr;
76
77 ReferenceFrameContext &rotate(Real, Vec3 const &);
78 ReferenceFrameContext &rotate(Real, Real, Real, Real);
79
80 ReferenceFrameContext &translate(Vec3 const &);
81 ReferenceFrameContext &translate(Real, Real, Real);
82
83 inline operator
84 ReferenceFrame *() const
85 {
86 return m_last;
87 }
88 };
89
90 enum BeamReference {
91 SkyRelative,
92 ElementRelative,
93 PlaneRelative
94 };
95
96 enum BeamShape {
97 Circular,
98 Ring,
99 Point,
100 Custom
101 };
102
103 enum FNumReference {
104 BeamDiameter,
105 BeamLength,
106 };
107
109 uint32_t id = 0;
110 BeamReference reference = SkyRelative;
111 BeamShape shape = Circular;
112 bool converging = true;
113
114 union {
115 const ReferenceFrame *frame = nullptr;
116 const Element *element;
117 };
118
119 std::string path;
120 Real length = 10; // [m]
121 Real diameter = .5; // [m]
122 Real wavelength = 535e-9;
123 unsigned int numRays = 1000;
124 bool random = false;
125 Vec3 direction = -Vec3::eZ(); // [1]
126 Vec3 offset = Vec3::zero(); // [m]
127 Real focusZ = 0; // [m]
128 bool vignetting = true;
129
130 // Object structure
131 SkyObjectShape objectShape = PointLike;
132 Real angularDiameter = M_PI / 6; // [1]
133 std::string objectPath;
134
135 //
136 // fNum = length / D This refers to beams that arrive as a circle.
137 //
138 inline void
139 setFNum(Real fNum, FNumReference adjust = BeamDiameter)
140 {
141 if (adjust == BeamDiameter)
142 diameter = length / fNum;
143 else
144 length = diameter * fNum;
145 }
146
147 //
148 // For object-like sources sometimes it is interesting to describe the
149 // illuminating cone froma f/#. The relationship between angular diameter
150 // and f/# is given by:
151 //
152 // a = 2 atan (0.5 / f)
153 //
154
155 inline void
156 setObjectFNum(Real fNum)
157 {
158 fNum = std::fabs(fNum);
159
160 if (std::isinf(fNum)) {
161 objectShape = PointLike;
162 } else {
163 objectShape = CircleLike;
164 angularDiameter = 2 * std::atan(0.5 / fNum);
165 }
166 }
167
168 inline void
169 collimate()
170 {
171 focusZ = -std::numeric_limits<Real>::infinity();
172 }
173
174 inline void
175 setElementRelative(const Element *element)
176 {
177 reference = ElementRelative;
178 this->element = element;
179 }
180
181 inline void
182 setPlaneRelative(const ReferenceFrame *frame)
183 {
184 reference = PlaneRelative;
185 this->frame = frame;
186 }
187
188 inline void
189 setObjectShape(std::string const &shape)
190 {
191 if (shape == "point")
192 this->objectShape = PointLike;
193 else if (shape == "circular")
194 this->objectShape = CircleLike;
195 else if (shape == "extended")
196 this->objectShape = Extended;
197 else
198 std::runtime_error("Unrecognized angular shape `" + shape + "'");
199 }
200
201 void debug() const;
202 };
203
204 class OMModel {
205 std::list<ReferenceFrame *> m_frames; // Frame allocation
206 std::map<std::string, ReferenceFrame *> m_nameToFrame; // Frame indexation
207
208 std::list<Element *> m_elements; // Element allocation
209 std::map<std::string, Element *> m_nameToElement; // Element indexation
210 std::map<std::string, OpticalElement *> m_nameToOpticalElement; // Element indexation
211
212 std::list<OpticalPath> m_paths; // Optical path allocation
213 std::map<std::string, OpticalPath *> m_nameToPath; // Path indexation
214 std::map<std::string, Detector *> m_nameToDetector;
215
216 // Convenience references
217 ReferenceFrame *m_world = nullptr;
218
219 // Convenience elements
220 RayBeamElement *m_beam = nullptr;
221 Simulation *m_sim = nullptr;
222
223 bool registerElement(Element *);
224 bool registerOpticalElement(OpticalElement *);
225 bool registerDetector(Detector *);
226
227 friend struct ReferenceFrameContext;
228
229 protected:
230 EvaluatedParameter *makeParameter(std::string const &, std::string const &);
231 std::string genElementName(std::string const &type);
232 std::string genReferenceFrameName(std::string const &type);
233
234 bool registerDetectorAlias(std::string const &name, Detector *);
235
236 public:
237 OMModel();
238 ~OMModel();
239
240 bool registerFrame(ReferenceFrame *);
241 void setFrameAlias(ReferenceFrame *, std::string const &name);
242 Element *autoRegisterElement(Element *);
243
244 inline ReferenceFrame *
245 world() const
246 {
247 return m_world;
248 }
249
250 inline Simulation *
251 simulation() const
252 {
253 return m_sim;
254 }
255
256 void linkWorld(ReferenceFrame *);
257
258 template <class T>
259 inline T *
260 plug(
261 std::string const &existing,
262 std::string const &port,
263 std::string const &type,
264 std::string const &name = "")
265 {
266 std::string rwName = name;
267 Element *element = lookupElementOrEx(existing);
268 T *newElement;
269
270 if (rwName.size() == 0)
271 rwName = genElementName(type);
272
273 if (lookupElement(rwName) != nullptr)
274 return nullptr;
275
276 return static_cast<T *>(
277 autoRegisterElement(element->plug<T>(port, type, rwName)));
278 }
279
280 template <class T>
281 inline T *
282 plug(
283 std::string const &existingFrame,
284 std::string const &type,
285 std::string const &name = "")
286 {
287 std::string rwName = name;
288 ReferenceFrame *frame = lookupReferenceFrameOrEx(existingFrame);
289
290 // Lookup factory for this element
291 RZ::Singleton *sing = RZ::Singleton::instance();
292 auto factory = sing->lookupElementFactory(type);
293
294 if (factory == nullptr)
295 throw std::runtime_error("Element class `" + type + "` does not exist");
296
297 // Sanitize name
298 if (rwName.size() == 0)
299 rwName = genElementName(type);
300
301 if (lookupElement(rwName) != nullptr)
302 return nullptr;
303
304 return static_cast<T *>(
305 autoRegisterElement(factory->make(rwName, frame)));
306 }
307
308 void recalculate();
309 RayBeamElement *beam() const;
310 void clearBeam();
311 void setBeamColoring(RayColoring const *coloring);
312
313 ReferenceFrameContext rotate(Real, Vec3 const &, ReferenceFrame *parent = nullptr);
314 ReferenceFrameContext rotate(Real, Real, Real, Real, ReferenceFrame *parent = nullptr);
315
316 ReferenceFrameContext translate(Vec3 const &, ReferenceFrame *parent = nullptr);
317 ReferenceFrameContext translate(Real, Real, Real, ReferenceFrame *parent = nullptr);
318
319 // Optical path configuration
320 bool addOpticalPath(std::string const &, std::list<std::string> const &); // Just elements
321 bool addDetector(
322 std::string const &name,
323 ReferenceFrame *pFrame,
324 unsigned int cols = RZ_DEFAULT_CCD_RESOLUTION,
325 unsigned int rows = RZ_DEFAULT_CCD_RESOLUTION,
326 Real width = RZ_DEFAULT_CCD_WIDTH,
327 Real height = RZ_DEFAULT_CCD_WIDTH);
328
329 bool addDetector(
330 std::string const &name,
331 std::string const &parentFrame,
332 unsigned int cols = RZ_DEFAULT_CCD_RESOLUTION,
333 unsigned int rows = RZ_DEFAULT_CCD_RESOLUTION,
334 Real width = RZ_DEFAULT_CCD_WIDTH,
335 Real height = RZ_DEFAULT_CCD_WIDTH);
336
337 // Enumeration methods
338 std::list<std::string> frames() const;
339 std::list<std::string> elements() const;
340 std::list<std::string> opticalElements() const;
341 std::list<std::string> detectors() const;
342 std::list<std::string> opticalPaths() const;
343 std::list<std::string> elementHierarchy(std::string const &pfx = "") const;
344 std::list<std::string> opticalElementHierarchy(std::string const &pfx = "") const;
345 void boundingBox(Vec3 &, Vec3 &) const;
346
347 // Convenience methods (fast enumeration)
348 std::list<Element *> const &elementList() const;
349 std::list<Element *> allElements() const;
350 std::list<OpticalElement *> allOpticalElements() const;
351
352 // Lookup methods
353 ReferenceFrame *lookupReferenceFrame(std::string const &) const;
354 Element *resolveElement(std::string const &) const;
355 Element *lookupElement(std::string const &) const;
356 OpticalElement *resolveOpticalElement(std::string const &) const;
357 OpticalElement *lookupOpticalElement(std::string const &) const;
358 Detector *lookupDetector(std::string const &) const;
359 const OpticalPath *lookupOpticalPath(std::string const & = "") const;
360
361 // Lookup methods (raise exception)
362 ReferenceFrame *lookupReferenceFrameOrEx(std::string const &) const;
363 Element *lookupElementOrEx(std::string const &) const;
364 OpticalElement *lookupOpticalElementOrEx(std::string const &) const;
365 Detector *lookupDetectorOrEx(std::string const &) const;
366 const OpticalPath *lookupOpticalPathOrEx(std::string const & = "") const;
367
368 // Raytracing methods
369 bool trace(
370 std::string const &path,
371 std::list<RZ::Ray> const &rays,
372 bool updateBeamElement = false,
373 RayTracingProcessListener *listener = nullptr,
374 bool clear = true,
375 const struct timeval *startTime = nullptr,
376 bool clearIntermediate = true);
377
378 bool traceDiffraction(
379 std::string const &path,
380 std::list<RZ::Ray> const &rays,
381 RayTracingProcessListener *listener = nullptr,
382 bool clear = true,
383 const struct timeval *startTime = nullptr);
384
385 bool traceDefault(
386 std::list<RZ::Ray> const &rays,
387 bool updateBeamElement = false,
388 RayTracingProcessListener *listener = nullptr,
389 bool clear = true,
390 const struct timeval *startTime = nullptr);
391
392 bool traceNonSequential(
393 std::list<RZ::Ray> const &rays,
394 bool updateBeamElement = false,
395 RayTracingProcessListener *listener = nullptr,
396 bool clear = true,
397 const struct timeval *startTime = nullptr,
398 bool clearIntermediate = true,
399 uint32_t maxProps = 3000);
400
401 struct timeval lastTracerTick() const;
402
403 // Save images
404 bool savePNG(
405 std::string const &detector,
406 std::string const &file);
407
408 static void addSkyBeam(
409 std::list<Ray> &dest,
410 unsigned int number = 1000,
411 Real radius = .5,
412 Real azimuth = 0,
413 Real elevation = 90,
414 Real distance = 10,
415 uint32_t id = 0,
416 bool random = true);
417
418 static void addElementRelativeBeam(
419 std::list<Ray> &dest,
420 Element *element,
421 unsigned int number = 1000,
422 Real radius = .5,
423 Real azimuth = 0,
424 Real elevation = 90,
425 Real offX = 0,
426 Real offY = 0,
427 Real distance = 10,
428 uint32_t id = 0,
429 bool random = true);
430
431 static void addElementRelativeFocusBeam(
432 std::list<Ray> &dest,
433 Element *element,
434 unsigned int number = 1000,
435 Real radius = .5,
436 Real fNum = 17.37,
437 Real refAperture = 200e-3,
438 Real azimuth = 0,
439 Real elevation = 90,
440 Real offX = 0,
441 Real offY = 0,
442 Real distance = 10,
443 uint32_t id = 0,
444 bool random = true);
445
446 static void addFocalPlaneFocusedBeam(
447 std::list<Ray> &dest,
448 const ReferenceFrame *focalPlane,
449 unsigned int number = 1000,
450 Real fNum = 17.37,
451 Real azimuth = 0,
452 Real elevation = 90,
453 Real offX = 0,
454 Real offY = 0,
455 Real distance = 10,
456 uint32_t id = 0,
457 bool random = true,
458 Real offZ = 0);
459
460 static void addBeam(std::list<Ray> &dest, BeamProperties const &);
461
462 };
463}
464
465#ifndef RZ_NO_HELPER_MACROS
466# define plugElement(parent, type) plug<type>(parent, STRINGIFY(type))
467# define plugElementName(parent, type, name) plug<type>(parent, STRINGIFY(type), name)
468#endif // RZ_NO_HELPER_MACROS
469
470#endif // _OMMODEL_H
Definition: Detector.h:116
Definition: Element.h:173
Definition: OMModel.h:204
Definition: OpticalElement.h:87
Definition: RayBeamElement.h:67
Definition: RayBeamElement.h:30
Definition: RayTracingEngine.h:38
Definition: ReferenceFrame.h:59
Definition: Simulation.h:50
Definition: Singleton.h:34
Definition: OMModel.h:108
Definition: OMModel.h:65
Definition: OpticalElement.h:54
Definition: OMModel.h:73
Definition: Vector.h:66