static void compute_enu_directions(oskar_Mem* x, oskar_Mem* y, oskar_Mem* z, int np, const oskar_Mem* l, const oskar_Mem* m, const oskar_Mem* n, const oskar_Station* station, double GAST, int* status) { double ha0, dec0; oskar_mem_ensure(x, np, status); oskar_mem_ensure(y, np, status); oskar_mem_ensure(z, np, status); if (*status) return; /* Obtain ra0, dec0 of phase centre */ const double lat = oskar_station_lat_rad(station); const int pointing_coord_type = oskar_station_beam_coord_type(station); if (pointing_coord_type == OSKAR_SPHERICAL_TYPE_EQUATORIAL) { const double ra0 = oskar_station_beam_lon_rad(station); ha0 = (GAST + oskar_station_lon_rad(station)) - ra0; dec0 = oskar_station_beam_lat_rad(station); } else if (pointing_coord_type == OSKAR_SPHERICAL_TYPE_AZEL) { /* TODO convert from az0, el0 to ha0, dec0 */ ha0 = 0.0; dec0 = 0.0; *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE; return; } else { *status = OSKAR_ERR_SETTINGS_TELESCOPE; return; } oskar_convert_relative_directions_to_enu_directions( 0, 0, 0, np, l, m, n, ha0, dec0, lat, 0, x, y, z, status); }
static void compute_relative_directions(oskar_Mem* l, oskar_Mem* m, oskar_Mem* n, int np, const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z, const oskar_Station* station, double GAST, int* status) { double ha0, dec0, lat; int pointing_coord_type; if (*status) return; /* Resize work arrays if needed */ if ((int)oskar_mem_length(l) < np) oskar_mem_realloc(l, np, status); if ((int)oskar_mem_length(m) < np) oskar_mem_realloc(m, np, status); if ((int)oskar_mem_length(n) < np) oskar_mem_realloc(n, np, status); if (*status) return; /* Obtain ra0, dec0 of phase centre */ lat = oskar_station_lat_rad(station); pointing_coord_type = oskar_station_beam_coord_type(station); if (pointing_coord_type == OSKAR_SPHERICAL_TYPE_EQUATORIAL) { double ra0; ra0 = oskar_station_beam_lon_rad(station); ha0 = (GAST + oskar_station_lon_rad(station)) - ra0; dec0 = oskar_station_beam_lat_rad(station); } else if (pointing_coord_type == OSKAR_SPHERICAL_TYPE_AZEL) { /* TODO convert from az0, el0 to ha0, dec0 */ ha0 = 0.0; dec0 = 0.0; *status = OSKAR_FAIL; return; } else { *status = OSKAR_ERR_SETTINGS_TELESCOPE; return; } /* Convert from ENU to phase-centre-relative directions. */ oskar_convert_enu_directions_to_relative_directions( l, m, n, np, x, y, z, ha0, dec0, lat, status); }
void oskar_evaluate_beam_horizon_direction(double* x, double* y, double* z, const oskar_Station* station, const double gast, int* status) { int beam_coord_type; double beam_lon, beam_lat; /* Check if safe to proceed. */ if (*status) return; /* Get direction cosines in horizontal coordinates. */ beam_coord_type = oskar_station_beam_coord_type(station); beam_lon = oskar_station_beam_lon_rad(station); beam_lat = oskar_station_beam_lat_rad(station); if (beam_coord_type == OSKAR_SPHERICAL_TYPE_EQUATORIAL) { double lon, lat, last; lon = oskar_station_lon_rad(station); lat = oskar_station_lat_rad(station); last = gast + lon; /* Local Apparent Sidereal Time, in radians. */ oskar_convert_apparent_ra_dec_to_enu_directions_d(1, &beam_lon, &beam_lat, last, lat, x, y, z); } else if (beam_coord_type == OSKAR_SPHERICAL_TYPE_AZEL) { /* Convert AZEL to direction cosines. */ double cos_lat; cos_lat = cos(beam_lat); *x = cos_lat * sin(beam_lon); *y = cos_lat * cos(beam_lon); *z = sin(beam_lat); } else { *status = OSKAR_ERR_INVALID_ARGUMENT; } /* Check if the beam direction needs to be one of a set of * allowed (az,el) directions. */ if (oskar_station_num_permitted_beams(station) > 0) { int i, n, min_index = 0; double az, el, cos_el, min_dist = DBL_MAX; const double *p_az, *p_el; /* Convert current direction cosines to azimuth, elevation. */ az = atan2(*x, *y); el = atan2(*z, sqrt(*x * *x + *y * *y)); /* Get pointers to permitted beam data. */ n = oskar_station_num_permitted_beams(station); p_az = oskar_mem_double_const( oskar_station_permitted_beam_az_rad_const(station), status); p_el = oskar_mem_double_const( oskar_station_permitted_beam_el_rad_const(station), status); /* Loop over permitted beams. */ for (i = 0; i < n; ++i) { double dist; dist = oskar_angular_distance(p_az[i], az, p_el[i], el); if (dist < min_dist) { min_dist = dist; min_index = i; } } /* Select beam azimuth and elevation based on minimum distance. */ az = p_az[min_index]; el = p_el[min_index]; /* Set new direction cosines. */ cos_el = cos(el); *x = cos_el * sin(az); *y = cos_el * cos(az); *z = sin(el); } }