1 /*
2  * Copyright (c) 2013-2021, The OSKAR Developers.
3  * See the LICENSE file at the top-level directory of this distribution.
4  */
5 
6 #include "telescope/station/private_station.h"
7 #include "telescope/station/oskar_station_accessors.h"
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 
14 /* Data common to all station types. */
15 
oskar_station_unique_id(const oskar_Station * model)16 int oskar_station_unique_id(const oskar_Station* model)
17 {
18     return model ? model->unique_id : 0;
19 }
20 
oskar_station_precision(const oskar_Station * model)21 int oskar_station_precision(const oskar_Station* model)
22 {
23     return model ? model->precision : 0;
24 }
25 
oskar_station_mem_location(const oskar_Station * model)26 int oskar_station_mem_location(const oskar_Station* model)
27 {
28     return model ? model->mem_location : 0;
29 }
30 
oskar_station_type(const oskar_Station * model)31 int oskar_station_type(const oskar_Station* model)
32 {
33     return model ? model->station_type : 0;
34 }
35 
oskar_station_normalise_final_beam(const oskar_Station * model)36 int oskar_station_normalise_final_beam(const oskar_Station* model)
37 {
38     return model ? model->normalise_final_beam : 0;
39 }
40 
oskar_station_lon_rad(const oskar_Station * model)41 double oskar_station_lon_rad(const oskar_Station* model)
42 {
43     return model ? model->lon_rad : 0.0;
44 }
45 
oskar_station_lat_rad(const oskar_Station * model)46 double oskar_station_lat_rad(const oskar_Station* model)
47 {
48     return model ? model->lat_rad : 0.0;
49 }
50 
oskar_station_alt_metres(const oskar_Station * model)51 double oskar_station_alt_metres(const oskar_Station* model)
52 {
53     return model ? model->alt_metres : 0.0;
54 }
55 
oskar_station_offset_ecef_x(const oskar_Station * model)56 double oskar_station_offset_ecef_x(const oskar_Station* model)
57 {
58     return model ? model->offset_ecef[0] : 0.0;
59 }
60 
oskar_station_offset_ecef_y(const oskar_Station * model)61 double oskar_station_offset_ecef_y(const oskar_Station* model)
62 {
63     return model ? model->offset_ecef[1] : 0.0;
64 }
65 
oskar_station_offset_ecef_z(const oskar_Station * model)66 double oskar_station_offset_ecef_z(const oskar_Station* model)
67 {
68     return model ? model->offset_ecef[2] : 0.0;
69 }
70 
oskar_station_polar_motion_x_rad(const oskar_Station * model)71 double oskar_station_polar_motion_x_rad(const oskar_Station* model)
72 {
73     return model ? model->pm_x_rad : 0.0;
74 }
75 
oskar_station_polar_motion_y_rad(const oskar_Station * model)76 double oskar_station_polar_motion_y_rad(const oskar_Station* model)
77 {
78     return model ? model->pm_y_rad : 0.0;
79 }
80 
oskar_station_beam_lon_rad(const oskar_Station * model)81 double oskar_station_beam_lon_rad(const oskar_Station* model)
82 {
83     return model ? model->beam_lon_rad : 0.0;
84 }
85 
oskar_station_beam_lat_rad(const oskar_Station * model)86 double oskar_station_beam_lat_rad(const oskar_Station* model)
87 {
88     return model ? model->beam_lat_rad : 0.0;
89 }
90 
oskar_station_beam_coord_type(const oskar_Station * model)91 int oskar_station_beam_coord_type(const oskar_Station* model)
92 {
93     return model ? model->beam_coord_type : 0;
94 }
95 
oskar_station_noise_freq_hz(oskar_Station * model)96 oskar_Mem* oskar_station_noise_freq_hz(oskar_Station* model)
97 {
98     return model ? model->noise_freq_hz : 0;
99 }
100 
oskar_station_noise_freq_hz_const(const oskar_Station * model)101 const oskar_Mem* oskar_station_noise_freq_hz_const(const oskar_Station* model)
102 {
103     return model ? model->noise_freq_hz : 0;
104 }
105 
oskar_station_noise_rms_jy(oskar_Station * model)106 oskar_Mem* oskar_station_noise_rms_jy(oskar_Station* model)
107 {
108     return model ? model->noise_rms_jy : 0;
109 }
110 
oskar_station_noise_rms_jy_const(const oskar_Station * model)111 const oskar_Mem* oskar_station_noise_rms_jy_const(const oskar_Station* model)
112 {
113     return model ? model->noise_rms_jy : 0;
114 }
115 
116 /* Data used only for Gaussian beam stations. */
117 
oskar_station_gaussian_beam_fwhm_rad(const oskar_Station * model)118 double oskar_station_gaussian_beam_fwhm_rad(const oskar_Station* model)
119 {
120     return model ? model->gaussian_beam_fwhm_rad : 0.0;
121 }
122 
oskar_station_gaussian_beam_reference_freq_hz(const oskar_Station * model)123 double oskar_station_gaussian_beam_reference_freq_hz(const oskar_Station* model)
124 {
125     return model ? model->gaussian_beam_reference_freq_hz : 0.0;
126 }
127 
128 /* Data used only for aperture array stations. */
129 
oskar_station_identical_children(const oskar_Station * model)130 int oskar_station_identical_children(const oskar_Station* model)
131 {
132     return model ? model->identical_children : 0;
133 }
134 
oskar_station_num_elements(const oskar_Station * model)135 int oskar_station_num_elements(const oskar_Station* model)
136 {
137     return model ? model->num_elements : 0;
138 }
139 
oskar_station_num_element_types(const oskar_Station * model)140 int oskar_station_num_element_types(const oskar_Station* model)
141 {
142     return model ? model->num_element_types : 0;
143 }
144 
oskar_station_normalise_array_pattern(const oskar_Station * model)145 int oskar_station_normalise_array_pattern(const oskar_Station* model)
146 {
147     return model ? model->normalise_array_pattern : 0;
148 }
149 
oskar_station_normalise_element_pattern(const oskar_Station * model)150 int oskar_station_normalise_element_pattern(const oskar_Station* model)
151 {
152     return model ? model->normalise_element_pattern : 0;
153 }
154 
oskar_station_enable_array_pattern(const oskar_Station * model)155 int oskar_station_enable_array_pattern(const oskar_Station* model)
156 {
157     return model ? model->enable_array_pattern : 0;
158 }
159 
oskar_station_common_element_orientation(const oskar_Station * model)160 int oskar_station_common_element_orientation(const oskar_Station* model)
161 {
162     return model ? model->common_element_orientation : 0;
163 }
164 
oskar_station_common_pol_beams(const oskar_Station * model)165 int oskar_station_common_pol_beams(const oskar_Station* model)
166 {
167     return model ? model->common_pol_beams : 0;
168 }
169 
oskar_station_array_is_3d(const oskar_Station * model)170 int oskar_station_array_is_3d(const oskar_Station* model)
171 {
172     return model ? model->array_is_3d : 0;
173 }
174 
oskar_station_apply_element_errors(const oskar_Station * model)175 int oskar_station_apply_element_errors(const oskar_Station* model)
176 {
177     return model ? model->apply_element_errors : 0;
178 }
179 
oskar_station_apply_element_weight(const oskar_Station * model)180 int oskar_station_apply_element_weight(const oskar_Station* model)
181 {
182     return model ? model->apply_element_weight : 0;
183 }
184 
oskar_station_seed_time_variable_errors(const oskar_Station * model)185 unsigned int oskar_station_seed_time_variable_errors(const oskar_Station* model)
186 {
187     return model ? model->seed_time_variable_errors : 0u;
188 }
189 
oskar_station_swap_xy(const oskar_Station * model)190 int oskar_station_swap_xy(const oskar_Station* model)
191 {
192     return model ? model->swap_xy : 0;
193 }
194 
oskar_station_element_euler_index_rad(const oskar_Station * model,int feed,int dim,int index)195 double oskar_station_element_euler_index_rad(
196         const oskar_Station* model, int feed, int dim, int index)
197 {
198     const oskar_Mem* ptr = 0;
199     if (!model || feed > 1 || dim > 2) return 0.0;
200     ptr = model->element_euler_cpu[feed][dim];
201     if (!ptr) ptr = model->element_euler_cpu[0][dim];
202     return ptr ? ((const double*) oskar_mem_void_const(ptr))[index] : 0.0;
203 }
204 
oskar_station_element_euler_rad(oskar_Station * model,int feed,int dim)205 oskar_Mem* oskar_station_element_euler_rad(
206         oskar_Station* model, int feed, int dim)
207 {
208     oskar_Mem* ptr = 0;
209     if (!model || feed > 1 || dim > 2) return 0;
210     ptr = model->element_euler_cpu[feed][dim];
211     return ptr ? ptr : model->element_euler_cpu[0][dim];
212 }
213 
oskar_station_element_euler_rad_const(const oskar_Station * model,int feed,int dim)214 const oskar_Mem* oskar_station_element_euler_rad_const(
215         const oskar_Station* model, int feed, int dim)
216 {
217     const oskar_Mem* ptr = 0;
218     if (!model || feed > 1 || dim > 2) return 0;
219     ptr = model->element_euler_cpu[feed][dim];
220     return ptr ? ptr : model->element_euler_cpu[0][dim];
221 }
222 
oskar_station_element_true_enu_metres(oskar_Station * model,int feed,int dim)223 oskar_Mem* oskar_station_element_true_enu_metres(
224         oskar_Station* model, int feed, int dim)
225 {
226     oskar_Mem* ptr = 0;
227     if (!model || feed > 1 || dim > 2) return 0;
228     ptr = model->element_true_enu_metres[feed][dim];
229     return ptr ? ptr : model->element_true_enu_metres[0][dim];
230 }
231 
oskar_station_element_true_enu_metres_const(const oskar_Station * model,int feed,int dim)232 const oskar_Mem* oskar_station_element_true_enu_metres_const(
233         const oskar_Station* model, int feed, int dim)
234 {
235     const oskar_Mem* ptr = 0;
236     if (!model || feed > 1 || dim > 2) return 0;
237     ptr = model->element_true_enu_metres[feed][dim];
238     return ptr ? ptr : model->element_true_enu_metres[0][dim];
239 }
240 
oskar_station_element_measured_enu_metres(oskar_Station * model,int feed,int dim)241 oskar_Mem* oskar_station_element_measured_enu_metres(
242         oskar_Station* model, int feed, int dim)
243 {
244     oskar_Mem* ptr = 0;
245     if (!model || feed > 1 || dim > 2) return 0;
246     ptr = model->element_measured_enu_metres[feed][dim];
247     return ptr ? ptr : model->element_measured_enu_metres[0][dim];
248 }
249 
oskar_station_element_measured_enu_metres_const(const oskar_Station * model,int feed,int dim)250 const oskar_Mem* oskar_station_element_measured_enu_metres_const(
251         const oskar_Station* model, int feed, int dim)
252 {
253     const oskar_Mem* ptr = 0;
254     if (!model || feed > 1 || dim > 2) return 0;
255     ptr = model->element_measured_enu_metres[feed][dim];
256     return ptr ? ptr : model->element_measured_enu_metres[0][dim];
257 }
258 
oskar_station_element_cable_length_error_metres(oskar_Station * model,int feed)259 oskar_Mem* oskar_station_element_cable_length_error_metres(
260         oskar_Station* model, int feed)
261 {
262     oskar_Mem* ptr = 0;
263     if (!model || feed > 1) return 0;
264     ptr = model->element_cable_length_error[feed];
265     return ptr ? ptr : model->element_cable_length_error[0];
266 }
267 
oskar_station_element_cable_length_error_metres_const(const oskar_Station * model,int feed)268 const oskar_Mem* oskar_station_element_cable_length_error_metres_const(
269         const oskar_Station* model, int feed)
270 {
271     const oskar_Mem* ptr = 0;
272     if (!model || feed > 1) return 0;
273     ptr = model->element_cable_length_error[feed];
274     return ptr ? ptr : model->element_cable_length_error[0];
275 }
276 
oskar_station_element_gain(oskar_Station * model,int feed)277 oskar_Mem* oskar_station_element_gain(oskar_Station* model, int feed)
278 {
279     oskar_Mem* ptr = 0;
280     if (!model || feed > 1) return 0;
281     ptr = model->element_gain[feed];
282     return ptr ? ptr : model->element_gain[0];
283 }
284 
oskar_station_element_gain_const(const oskar_Station * model,int feed)285 const oskar_Mem* oskar_station_element_gain_const(
286         const oskar_Station* model, int feed)
287 {
288     const oskar_Mem* ptr = 0;
289     if (!model || feed > 1) return 0;
290     ptr = model->element_gain[feed];
291     return ptr ? ptr : model->element_gain[0];
292 }
293 
oskar_station_element_gain_error(oskar_Station * model,int feed)294 oskar_Mem* oskar_station_element_gain_error(oskar_Station* model, int feed)
295 {
296     oskar_Mem* ptr = 0;
297     if (!model || feed > 1) return 0;
298     ptr = model->element_gain_error[feed];
299     return ptr ? ptr : model->element_gain_error[0];
300 }
301 
oskar_station_element_gain_error_const(const oskar_Station * model,int feed)302 const oskar_Mem* oskar_station_element_gain_error_const(
303         const oskar_Station* model, int feed)
304 {
305     const oskar_Mem* ptr = 0;
306     if (!model || feed > 1) return 0;
307     ptr = model->element_gain_error[feed];
308     return ptr ? ptr : model->element_gain_error[0];
309 }
310 
oskar_station_element_phase_offset_rad(oskar_Station * model,int feed)311 oskar_Mem* oskar_station_element_phase_offset_rad(
312         oskar_Station* model, int feed)
313 {
314     oskar_Mem* ptr = 0;
315     if (!model || feed > 1) return 0;
316     ptr = model->element_phase_offset_rad[feed];
317     return ptr ? ptr : model->element_phase_offset_rad[0];
318 }
319 
oskar_station_element_phase_offset_rad_const(const oskar_Station * model,int feed)320 const oskar_Mem* oskar_station_element_phase_offset_rad_const(
321         const oskar_Station* model, int feed)
322 {
323     const oskar_Mem* ptr = 0;
324     if (!model || feed > 1) return 0;
325     ptr = model->element_phase_offset_rad[feed];
326     return ptr ? ptr : model->element_phase_offset_rad[0];
327 }
328 
oskar_station_element_phase_error_rad(oskar_Station * model,int feed)329 oskar_Mem* oskar_station_element_phase_error_rad(
330         oskar_Station* model, int feed)
331 {
332     oskar_Mem* ptr = 0;
333     if (!model || feed > 1) return 0;
334     ptr = model->element_phase_error_rad[feed];
335     return ptr ? ptr : model->element_phase_error_rad[0];
336 }
337 
oskar_station_element_phase_error_rad_const(const oskar_Station * model,int feed)338 const oskar_Mem* oskar_station_element_phase_error_rad_const(
339         const oskar_Station* model, int feed)
340 {
341     const oskar_Mem* ptr = 0;
342     if (!model || feed > 1) return 0;
343     ptr = model->element_phase_error_rad[feed];
344     return ptr ? ptr : model->element_phase_error_rad[0];
345 }
346 
oskar_station_element_weight(oskar_Station * model,int feed)347 oskar_Mem* oskar_station_element_weight(oskar_Station* model, int feed)
348 {
349     oskar_Mem* ptr = 0;
350     if (!model || feed > 1) return 0;
351     ptr = model->element_weight[feed];
352     return ptr ? ptr : model->element_weight[0];
353 }
354 
oskar_station_element_weight_const(const oskar_Station * model,int feed)355 const oskar_Mem* oskar_station_element_weight_const(
356         const oskar_Station* model, int feed)
357 {
358     const oskar_Mem* ptr = 0;
359     if (!model || feed > 1) return 0;
360     ptr = model->element_weight[feed];
361     return ptr ? ptr : model->element_weight[0];
362 }
363 
oskar_station_element_types(oskar_Station * model)364 oskar_Mem* oskar_station_element_types(oskar_Station* model)
365 {
366     return model ? model->element_types : 0;
367 }
368 
oskar_station_element_types_const(const oskar_Station * model)369 const oskar_Mem* oskar_station_element_types_const(const oskar_Station* model)
370 {
371     return model ? model->element_types : 0;
372 }
373 
oskar_station_element_types_cpu_const(const oskar_Station * model)374 const int* oskar_station_element_types_cpu_const(const oskar_Station* model)
375 {
376     if (!model) return 0;
377     return (const int*) oskar_mem_void_const(model->element_types_cpu);
378 }
379 
oskar_station_element_mount_types_const(const oskar_Station * model)380 const char* oskar_station_element_mount_types_const(const oskar_Station* model)
381 {
382     if (!model) return 0;
383     return oskar_mem_char_const(model->element_mount_types_cpu);
384 }
385 
oskar_station_has_child(const oskar_Station * model)386 int oskar_station_has_child(const oskar_Station* model)
387 {
388     return model ? (model->child ? 1 : 0) : 0;
389 }
390 
oskar_station_child(oskar_Station * model,int i)391 oskar_Station* oskar_station_child(oskar_Station* model, int i)
392 {
393     return model ? model->child[i] : 0;
394 }
395 
oskar_station_child_const(const oskar_Station * model,int i)396 const oskar_Station* oskar_station_child_const(const oskar_Station* model,
397         int i)
398 {
399     return model ? model->child[i] : 0;
400 }
401 
oskar_station_has_element(const oskar_Station * model)402 int oskar_station_has_element(const oskar_Station* model)
403 {
404     return model ? (model->element ? 1 : 0) : 0;
405 }
406 
oskar_station_element(oskar_Station * model,int element_type_index)407 oskar_Element* oskar_station_element(oskar_Station* model,
408         int element_type_index)
409 {
410     return model ? model->element[element_type_index] : 0;
411 }
412 
oskar_station_element_const(const oskar_Station * model,int element_type_index)413 const oskar_Element* oskar_station_element_const(const oskar_Station* model,
414         int element_type_index)
415 {
416     return model ? model->element[element_type_index] : 0;
417 }
418 
oskar_station_num_permitted_beams(const oskar_Station * model)419 int oskar_station_num_permitted_beams(const oskar_Station* model)
420 {
421     return model ? model->num_permitted_beams : 0;
422 }
423 
oskar_station_permitted_beam_az_rad_const(const oskar_Station * model)424 const oskar_Mem* oskar_station_permitted_beam_az_rad_const(
425         const oskar_Station* model)
426 {
427     return model ? model->permitted_beam_az_rad : 0;
428 }
429 
oskar_station_permitted_beam_el_rad_const(const oskar_Station * model)430 const oskar_Mem* oskar_station_permitted_beam_el_rad_const(
431         const oskar_Station* model)
432 {
433     return model ? model->permitted_beam_el_rad : 0;
434 }
435 
436 
437 /* Setters. */
438 
oskar_station_set_unique_ids(oskar_Station * model,int * counter)439 void oskar_station_set_unique_ids(oskar_Station* model, int* counter)
440 {
441     if (!model) return;
442     model->unique_id = (*counter)++;
443     if (model->child)
444     {
445         int i = 0;
446         for (i = 0; i < model->num_elements; ++i)
447         {
448             oskar_station_set_unique_ids(model->child[i], counter);
449         }
450     }
451 }
452 
oskar_station_set_station_type(oskar_Station * model,int type)453 void oskar_station_set_station_type(oskar_Station* model, int type)
454 {
455     if (!model) return;
456     model->station_type = type;
457 }
458 
oskar_station_set_normalise_final_beam(oskar_Station * model,int value)459 void oskar_station_set_normalise_final_beam(oskar_Station* model, int value)
460 {
461     if (!model) return;
462     model->normalise_final_beam = value;
463 }
464 
oskar_station_set_position(oskar_Station * model,double longitude_rad,double latitude_rad,double altitude_m,double offset_ecef_x,double offset_ecef_y,double offset_ecef_z)465 void oskar_station_set_position(oskar_Station* model,
466         double longitude_rad, double latitude_rad, double altitude_m,
467         double offset_ecef_x, double offset_ecef_y, double offset_ecef_z)
468 {
469     if (!model) return;
470     model->lon_rad = longitude_rad;
471     model->lat_rad = latitude_rad;
472     model->alt_metres = altitude_m;
473     model->offset_ecef[0] = offset_ecef_x;
474     model->offset_ecef[1] = offset_ecef_y;
475     model->offset_ecef[2] = offset_ecef_z;
476 }
477 
oskar_station_set_polar_motion(oskar_Station * model,double pm_x_rad,double pm_y_rad)478 void oskar_station_set_polar_motion(oskar_Station* model,
479         double pm_x_rad, double pm_y_rad)
480 {
481     int i = 0;
482     if (!model) return;
483     model->pm_x_rad = pm_x_rad;
484     model->pm_y_rad = pm_y_rad;
485 
486     /* Set recursively for all child stations. */
487     if (oskar_station_has_child(model))
488     {
489         for (i = 0; i < model->num_elements; ++i)
490         {
491             oskar_station_set_polar_motion(model->child[i], pm_x_rad, pm_y_rad);
492         }
493     }
494 }
495 
oskar_station_set_phase_centre(oskar_Station * model,int coord_type,double longitude_rad,double latitude_rad)496 void oskar_station_set_phase_centre(oskar_Station* model,
497         int coord_type, double longitude_rad, double latitude_rad)
498 {
499     if (!model) return;
500     model->beam_coord_type = coord_type;
501     model->beam_lon_rad = longitude_rad;
502     model->beam_lat_rad = latitude_rad;
503 }
504 
oskar_station_set_gaussian_beam_values(oskar_Station * model,double fwhm_rad,double ref_freq_hz)505 void oskar_station_set_gaussian_beam_values(oskar_Station* model,
506         double fwhm_rad, double ref_freq_hz)
507 {
508     if (!model) return;
509     model->gaussian_beam_fwhm_rad = fwhm_rad;
510     model->gaussian_beam_reference_freq_hz = ref_freq_hz;
511 }
512 
oskar_station_set_normalise_array_pattern(oskar_Station * model,int value)513 void oskar_station_set_normalise_array_pattern(oskar_Station* model, int value)
514 {
515     if (!model) return;
516     model->normalise_array_pattern = value;
517 }
518 
oskar_station_set_normalise_element_pattern(oskar_Station * model,int value)519 void oskar_station_set_normalise_element_pattern(oskar_Station* model, int value)
520 {
521     if (!model) return;
522     model->normalise_element_pattern = value;
523 }
524 
oskar_station_set_enable_array_pattern(oskar_Station * model,int value)525 void oskar_station_set_enable_array_pattern(oskar_Station* model, int value)
526 {
527     if (!model) return;
528     model->enable_array_pattern = value;
529 }
530 
oskar_station_set_seed_time_variable_errors(oskar_Station * model,unsigned int value)531 void oskar_station_set_seed_time_variable_errors(oskar_Station* model,
532         unsigned int value)
533 {
534     if (!model) return;
535     model->seed_time_variable_errors = value;
536 }
537 
oskar_station_set_swap_xy(oskar_Station * model,int value)538 void oskar_station_set_swap_xy(oskar_Station* model, int value)
539 {
540     if (!model) return;
541     model->swap_xy = value;
542 }
543 
544 #ifdef __cplusplus
545 }
546 #endif
547