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);
}
Exemple #2
0
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, lat;
    int pointing_coord_type;

    if (*status) return;

    /* Resize work arrays if needed */
    if ((int)oskar_mem_length(x) < np) oskar_mem_realloc(x, np, status);
    if ((int)oskar_mem_length(y) < np) oskar_mem_realloc(y, np, status);
    if ((int)oskar_mem_length(z) < np) oskar_mem_realloc(z, 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 phase-centre-relative to ENU directions. */
    oskar_convert_relative_directions_to_enu_directions(
            x, y, z, np, l, m, n, ha0, dec0, lat, status);
}
Exemple #3
0
void oskar_evaluate_jones_Z(oskar_Jones* Z, const oskar_Sky* sky,
        const oskar_Telescope* telescope,
        const oskar_SettingsIonosphere* settings, double gast,
        double frequency_hz, oskar_WorkJonesZ* work, int* status)
{
    int i, num_sources, num_stations;
    /* Station position in ECEF frame */
    double station_x, station_y, station_z, wavelength;
    oskar_Mem *Z_station;
    int type;
    oskar_Sky* sky_cpu; /* Copy of the sky model on the CPU */

    /* Check if safe to proceed. */
    if (*status) return;

    /* Check data types. */
    type = oskar_sky_precision(sky);
    if (oskar_telescope_precision(telescope) != type ||
            oskar_jones_type(Z) != (type | OSKAR_COMPLEX) ||
            oskar_work_jones_z_type(work) != type)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }

    /* For now, this function requires data is on the CPU .. check this. */

    /* Resize the work array (if needed) */
    num_stations = oskar_telescope_num_stations(telescope);
    num_sources = oskar_sky_num_sources(sky);
    oskar_work_jones_z_resize(work, num_sources, status);

    /* Copy the sky model to the CPU. */
    sky_cpu = oskar_sky_create_copy(sky, OSKAR_CPU, status);

    Z_station = oskar_mem_create_alias(0, 0, 0, status);
    wavelength = 299792458.0 / frequency_hz;

    /* Evaluate the ionospheric phase screen for each station at each
     * source pierce point. */
    for (i = 0; i < num_stations; ++i)
    {
        double last, lon, lat;
        const oskar_Station* station;
        station = oskar_telescope_station_const(telescope, i);
        lon = oskar_station_lon_rad(station);
        lat = oskar_station_lat_rad(station);
        last = gast + lon;

        /* Evaluate horizontal x,y,z source positions (for which to evaluate
         * pierce points) */
        oskar_convert_relative_directions_to_enu_directions(
                work->hor_x, work->hor_y, work->hor_z, num_sources,
                oskar_sky_l_const(sky_cpu), oskar_sky_m_const(sky_cpu),
                oskar_sky_n_const(sky_cpu), last - oskar_sky_reference_ra_rad(sky_cpu),
                oskar_sky_reference_dec_rad(sky_cpu), lat, status);

        /* Obtain station coordinates in the ECEF frame. */
        evaluate_station_ECEF_coords(&station_x, &station_y, &station_z, i,
                telescope);

        /* Obtain the pierce points. */
        /* FIXME(BM) this is current hard-coded to TID height screen 0
         * this fix is only needed to support multiple screen heights. */
        oskar_evaluate_pierce_points(work->pp_lon, work->pp_lat,
                work->pp_rel_path, station_x, station_y,
                station_z, settings->TID[0].height_km * 1000., num_sources,
                work->hor_x, work->hor_y, work->hor_z, status);

        /* Evaluate TEC values for the pierce points */
        oskar_evaluate_TEC(work, num_sources, settings, gast, status);

        /* Get a pointer to the Jones matrices for the station */
        oskar_jones_get_station_pointer(Z_station, Z, i, status);

        /* Populate the Jones matrix with ionospheric phase */
        evaluate_jones_Z_station(Z_station, wavelength,
                work->total_TEC, work->hor_z, settings->min_elevation,
                num_sources, status);
    }

    oskar_sky_free(sky_cpu, status);
    oskar_mem_free(Z_station, status);
}
void oskar_evaluate_station_beam(int num_points,
        int coord_type, oskar_Mem* x, oskar_Mem* y, oskar_Mem* z,
        double norm_ra_rad, double norm_dec_rad, const oskar_Station* station,
        oskar_StationWork* work, int time_index, double frequency_hz,
        double GAST, int offset_out, oskar_Mem* beam, int* status)
{
    oskar_Mem* out;
    const size_t num_points_orig = (size_t)num_points;
    if (*status) return;

    /* Set output beam array to work buffer. */
    out = oskar_station_work_beam_out(work, beam, num_points_orig, status);

    /* Check that the arrays have enough space to add an extra source at the
     * end (for normalisation). We don't want to reallocate here, since that
     * will be slow to do each time: must simply ensure that we pass input
     * arrays that are large enough.
     * The normalisation doesn't need to happen if the station has an
     * isotropic beam. */
    const int normalise = oskar_station_normalise_final_beam(station) &&
            (oskar_station_type(station) != OSKAR_STATION_TYPE_ISOTROPIC);
    if (normalise)
    {
        /* Increment number of points. */
        num_points++;

        /* Check the input arrays are big enough to hold the new source. */
        if ((int)oskar_mem_length(x) < num_points ||
                (int)oskar_mem_length(y) < num_points ||
                (int)oskar_mem_length(z) < num_points)
        {
            *status = OSKAR_ERR_DIMENSION_MISMATCH;
            return;
        }

        /* Get the beam direction in the appropriate coordinate system. */
        const int bypass = (coord_type != OSKAR_ENU_DIRECTIONS);
        const double ha0 = GAST + oskar_station_lon_rad(station) - norm_ra_rad;
        const double lat = oskar_station_lat_rad(station);
        oskar_convert_relative_directions_to_enu_directions(1, bypass, 0,
                1, 0, 0, 0, ha0, norm_dec_rad, lat, num_points - 1, x, y, z,
                status);
    }

    /* Evaluate the station beam for the given directions. */
    if (coord_type == OSKAR_ENU_DIRECTIONS)
        evaluate_station_beam_enu_directions(out, num_points, x, y, z,
                station, work, time_index, frequency_hz, GAST, status);
    else if (coord_type == OSKAR_RELATIVE_DIRECTIONS)
        evaluate_station_beam_relative_directions(out, num_points, x, y, z,
                station, work, time_index, frequency_hz, GAST, status);
    else
        *status = OSKAR_ERR_INVALID_ARGUMENT;

    /* Scale beam pattern by amplitude at the last source if required. */
    if (normalise)
        oskar_mem_normalise(out, 0, oskar_mem_length(out),
                num_points - 1, status);

    /* Copy output beam data. */
    oskar_mem_copy_contents(beam, out, offset_out, 0, num_points_orig, status);
}