예제 #1
0
void oskar_imager_update_plane_fft(oskar_Imager* h, int num_vis,
        const oskar_Mem* uu, const oskar_Mem* vv, const oskar_Mem* amps,
        const oskar_Mem* weight, oskar_Mem* plane, double* plane_norm,
        int* status)
{
    int num_cells, num_skipped = 0;
    if (*status) return;
    num_cells = h->grid_size * h->grid_size;
    if (oskar_mem_precision(plane) != h->imager_prec)
        *status = OSKAR_ERR_TYPE_MISMATCH;
    if ((int)oskar_mem_length(plane) < num_cells)
        oskar_mem_realloc(plane, num_cells, status);
    if (*status) return;
    if (h->imager_prec == OSKAR_DOUBLE)
        oskar_grid_simple_d(h->support, h->oversample,
                oskar_mem_double_const(h->conv_func, status), num_vis,
                oskar_mem_double_const(uu, status),
                oskar_mem_double_const(vv, status),
                oskar_mem_double_const(amps, status),
                oskar_mem_double_const(weight, status), h->cellsize_rad,
                h->grid_size, &num_skipped, plane_norm,
                oskar_mem_double(plane, status));
    else
        oskar_grid_simple_f(h->support, h->oversample,
                oskar_mem_double_const(h->conv_func, status), num_vis,
                oskar_mem_float_const(uu, status),
                oskar_mem_float_const(vv, status),
                oskar_mem_float_const(amps, status),
                oskar_mem_float_const(weight, status), h->cellsize_rad,
                h->grid_size, &num_skipped, plane_norm,
                oskar_mem_float(plane, status));
    if (num_skipped > 0)
        printf("WARNING: Skipped %d visibility points.\n", num_skipped);
}
예제 #2
0
static void evaluate_jones_Z_station(oskar_Mem* Z_station,
        double wavelength, const oskar_Mem* TEC, const oskar_Mem* hor_z,
        double min_elevation, int num_pp, int* status)
{
    int i, type;
    double arg;

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

    type = oskar_mem_type(Z_station);
    if (type == OSKAR_DOUBLE_COMPLEX)
    {
        double2* Z = oskar_mem_double2(Z_station, status);
        for (i = 0; i < num_pp; ++i)
        {
            /* Initialise as an unit scalar Z = (1 + 0i) i.e. no phase change */
            Z[i].x = 1.0;
            Z[i].y = 0.0;

            /* If the pierce point is below the minimum specified elevation
             * don't evaluate a phase */
            if (asin((oskar_mem_double_const(hor_z, status))[i]) <
                    min_elevation)
                continue;

            arg = wavelength * 25. * oskar_mem_double_const(TEC, status)[i];

            /* Z phase == exp(i * lambda * 25 * tec) */
            Z[i].x = cos(arg);
            Z[i].y = sin(arg);
        }
    }
    else if (type == OSKAR_SINGLE_COMPLEX)
    {
        float2* Z = oskar_mem_float2(Z_station, status);
        for (i = 0; i < num_pp; ++i)
        {
            /* Initialise as an unit scalar Z = (1 + 0i) i.e. no phase change */
            Z[i].x = 1.0;
            Z[i].y = 0.0;

            /* If the pierce point is below the minimum specified elevation
             * don't evaluate a phase */
            if (asin((oskar_mem_float_const(hor_z, status))[i]) <
                    min_elevation)
                continue;

            arg = wavelength * 25. * oskar_mem_float_const(TEC, status)[i];

            /* Z phase == exp(i * lambda * 25 * tec) */
            Z[i].x = cos(arg);
            Z[i].y = sin(arg);
        }
    }
    else
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
}
void oskar_convert_station_uvw_to_baseline_uvw(int num_stations, int offset_in,
        const oskar_Mem* u, const oskar_Mem* v, const oskar_Mem* w,
        int offset_out, oskar_Mem* uu, oskar_Mem* vv, oskar_Mem* ww,
        int* status)
{
    if (*status) return;
    const int type = oskar_mem_type(u);
    const int location = oskar_mem_location(u);
    if (location == OSKAR_CPU)
    {
        if (type == OSKAR_SINGLE)
            convert_station_uvw_to_baseline_uvw_float(num_stations, offset_in,
                    oskar_mem_float_const(u, status),
                    oskar_mem_float_const(v, status),
                    oskar_mem_float_const(w, status), offset_out,
                    oskar_mem_float(uu, status),
                    oskar_mem_float(vv, status),
                    oskar_mem_float(ww, status));
        else if (type == OSKAR_DOUBLE)
            convert_station_uvw_to_baseline_uvw_double(num_stations, offset_in,
                    oskar_mem_double_const(u, status),
                    oskar_mem_double_const(v, status),
                    oskar_mem_double_const(w, status), offset_out,
                    oskar_mem_double(uu, status),
                    oskar_mem_double(vv, status),
                    oskar_mem_double(ww, status));
        else
            *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
    else
    {
        size_t local_size[] = {32, 1, 1}, global_size[] = {1, 1, 1};
        const char* k = 0;
        if (type == OSKAR_SINGLE)
            k = "convert_station_uvw_to_baseline_uvw_float";
        else if (type == OSKAR_DOUBLE)
            k = "convert_station_uvw_to_baseline_uvw_double";
        else
        {
            *status = OSKAR_ERR_BAD_DATA_TYPE;
            return;
        }
        oskar_device_check_local_size(location, 0, local_size);
        global_size[0] = num_stations * local_size[0];
        const oskar_Arg args[] = {
                {INT_SZ, &num_stations},
                {INT_SZ, &offset_in},
                {PTR_SZ, oskar_mem_buffer_const(u)},
                {PTR_SZ, oskar_mem_buffer_const(v)},
                {PTR_SZ, oskar_mem_buffer_const(w)},
                {INT_SZ, &offset_out},
                {PTR_SZ, oskar_mem_buffer(uu)},
                {PTR_SZ, oskar_mem_buffer(vv)},
                {PTR_SZ, oskar_mem_buffer(ww)}
        };
        oskar_device_launch_kernel(k, location, 1, local_size, global_size,
                sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status);
    }
}
예제 #4
0
int oskar_find_closest_match(double value, const oskar_Mem* values,
        int* status)
{
    int type, num_values, match_index = 0;

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

    /* Check location. */
    if (oskar_mem_location(values) != OSKAR_CPU)
    {
        *status = OSKAR_ERR_BAD_LOCATION;
        return 0;
    }

    /* Switch on type. */
    type = oskar_mem_type(values);
    num_values = (int)oskar_mem_length(values);
    if (type == OSKAR_DOUBLE)
    {
        match_index = oskar_find_closest_match_d(value, num_values,
                oskar_mem_double_const(values, status));
    }
    else if (type == OSKAR_SINGLE)
    {
        match_index = oskar_find_closest_match_f(value, num_values,
                oskar_mem_float_const(values, status));
    }
    else
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
    return match_index;
}
예제 #5
0
void copy_vis_pol(oskar_Mem* amps, oskar_Mem* wt, int amps_offset,
        const oskar_Mem* vis, const oskar_Mem* weight, int vis_offset,
        int weight_offset, int num_baselines, int stride, int pol_offset,
        int* status)
{
    int i;
    if (*status) return;
    if (oskar_mem_precision(amps) == OSKAR_SINGLE)
    {
        float* w_out;
        const float* w_in;
        w_out = oskar_mem_float(wt, status) + amps_offset;
        w_in = oskar_mem_float_const(weight, status);
        for (i = 0; i < num_baselines; ++i)
            w_out[i] = w_in[stride * (weight_offset + i) + pol_offset];

        if (vis)
        {
            float2* a;
            const float2* v;
            a = oskar_mem_float2(amps, status) + amps_offset;
            v = oskar_mem_float2_const(vis, status);
            for (i = 0; i < num_baselines; ++i)
                a[i] = v[stride * (vis_offset + i) + pol_offset];
        }
    }
    else
    {
        double* w_out;
        const double* w_in;
        w_out = oskar_mem_double(wt, status) + amps_offset;
        w_in = oskar_mem_double_const(weight, status);
        for (i = 0; i < num_baselines; ++i)
            w_out[i] = w_in[stride * (weight_offset + i) + pol_offset];

        if (vis)
        {
            double2* a;
            const double2* v;
            a = oskar_mem_double2(amps, status) + amps_offset;
            v = oskar_mem_double2_const(vis, status);
            for (i = 0; i < num_baselines; ++i)
                a[i] = v[stride * (vis_offset + i) + pol_offset];
        }
    }
}
예제 #6
0
static void convert_complex(const oskar_Mem* input, oskar_Mem* output,
        int offset, int* status)
{
    size_t i, num_elements;
    if (*status) return;
    num_elements = oskar_mem_length(input);
    if (oskar_mem_precision(input) == OSKAR_SINGLE)
    {
        const float *in;
        float *out;
        in = oskar_mem_float_const(input, status);
        out = oskar_mem_float(output, status);
        for (i = 0; i < num_elements; ++i) out[i] = in[2*i + offset];
    }
    else
    {
        const double *in;
        double *out;
        in = oskar_mem_double_const(input, status);
        out = oskar_mem_double(output, status);
        for (i = 0; i < num_elements; ++i) out[i] = in[2*i + offset];
    }
}
void oskar_evaluate_element_weights_dft(int num_elements,
        const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z,
        double wavenumber, double x_beam, double y_beam, double z_beam,
        oskar_Mem* weights, int* status)
{
    if (*status) return;
    const int location = oskar_mem_location(weights);
    const int type = oskar_mem_type(weights);
    const int precision = oskar_mem_precision(weights);
    if (oskar_mem_location(x) != location ||
            oskar_mem_location(y) != location ||
            oskar_mem_location(z) != location)
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }
    if (oskar_mem_type(x) != precision || oskar_mem_type(y) != precision ||
            oskar_mem_type(z) != precision)
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if ((int)oskar_mem_length(weights) < num_elements ||
            (int)oskar_mem_length(x) < num_elements ||
            (int)oskar_mem_length(y) < num_elements ||
            (int)oskar_mem_length(z) < num_elements)
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }
    if (location == OSKAR_CPU)
    {
        if (type == OSKAR_DOUBLE_COMPLEX)
            evaluate_element_weights_dft_d(num_elements,
                    oskar_mem_double_const(x, status),
                    oskar_mem_double_const(y, status),
                    oskar_mem_double_const(z, status),
                    wavenumber, x_beam, y_beam, z_beam,
                    oskar_mem_double2(weights, status));
        else if (type == OSKAR_SINGLE_COMPLEX)
            evaluate_element_weights_dft_f(num_elements,
                    oskar_mem_float_const(x, status),
                    oskar_mem_float_const(y, status),
                    oskar_mem_float_const(z, status),
                    wavenumber, x_beam, y_beam, z_beam,
                    oskar_mem_float2(weights, status));
        else
            *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
    else
    {
        size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1};
        const char* k = 0;
        const int is_dbl = oskar_mem_is_double(weights);
        if (type == OSKAR_DOUBLE_COMPLEX)
            k = "evaluate_element_weights_dft_double";
        else if (type == OSKAR_SINGLE_COMPLEX)
            k = "evaluate_element_weights_dft_float";
        else
        {
            *status = OSKAR_ERR_BAD_DATA_TYPE;
            return;
        }
        const float w = (float) wavenumber;
        const float x1 = (float) x_beam;
        const float y1 = (float) y_beam;
        const float z1 = (float) z_beam;
        oskar_device_check_local_size(location, 0, local_size);
        global_size[0] = oskar_device_global_size(
                (size_t) num_elements, local_size[0]);
        const oskar_Arg args[] = {
                {INT_SZ, &num_elements},
                {PTR_SZ, oskar_mem_buffer_const(x)},
                {PTR_SZ, oskar_mem_buffer_const(y)},
                {PTR_SZ, oskar_mem_buffer_const(z)},
                {is_dbl ? DBL_SZ : FLT_SZ,
                        is_dbl ? (const void*)&wavenumber : (const void*)&w},
                {is_dbl ? DBL_SZ : FLT_SZ,
                        is_dbl ? (const void*)&x_beam : (const void*)&x1},
                {is_dbl ? DBL_SZ : FLT_SZ,
                        is_dbl ? (const void*)&y_beam : (const void*)&y1},
                {is_dbl ? DBL_SZ : FLT_SZ,
                        is_dbl ? (const void*)&z_beam : (const void*)&z1},
                {PTR_SZ, oskar_mem_buffer(weights)}
        };
        oskar_device_launch_kernel(k, location, 1, local_size, global_size,
                sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status);
    }
}
예제 #8
0
void oskar_blank_below_horizon(int offset_mask, int num_sources,
        const oskar_Mem* mask, int offset_out, oskar_Mem* data, int* status)
{
    if (*status) return;
    const int location = oskar_mem_location(data);
    if (oskar_mem_location(mask) != location)
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }
    if (oskar_mem_type(mask) != oskar_mem_precision(data))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if ((int)oskar_mem_length(data) < num_sources)
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }
    if (location == OSKAR_CPU)
    {
        switch (oskar_mem_type(data))
        {
        case OSKAR_DOUBLE_COMPLEX_MATRIX:
            blank_below_horizon_matrix_d(offset_mask, num_sources,
                    oskar_mem_double_const(mask, status), offset_out,
                    oskar_mem_double4c(data, status));
            break;
        case OSKAR_DOUBLE_COMPLEX:
            blank_below_horizon_scalar_d(offset_mask, num_sources,
                    oskar_mem_double_const(mask, status), offset_out,
                    oskar_mem_double2(data, status));
            break;
        case OSKAR_SINGLE_COMPLEX_MATRIX:
            blank_below_horizon_matrix_f(offset_mask, num_sources,
                    oskar_mem_float_const(mask, status), offset_out,
                    oskar_mem_float4c(data, status));
            break;
        case OSKAR_SINGLE_COMPLEX:
            blank_below_horizon_scalar_f(offset_mask, num_sources,
                    oskar_mem_float_const(mask, status), offset_out,
                    oskar_mem_float2(data, status));
            break;
        default:
            *status = OSKAR_ERR_BAD_DATA_TYPE;
            break;
        }
    }
    else
    {
        size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1};
        const char* k = 0;
        switch (oskar_mem_type(data))
        {
        case OSKAR_DOUBLE_COMPLEX_MATRIX:
            k = "blank_below_horizon_matrix_double"; break;
        case OSKAR_DOUBLE_COMPLEX:
            k = "blank_below_horizon_scalar_double"; break;
        case OSKAR_SINGLE_COMPLEX_MATRIX:
            k = "blank_below_horizon_matrix_float"; break;
        case OSKAR_SINGLE_COMPLEX:
            k = "blank_below_horizon_scalar_float"; break;
        default:
            *status = OSKAR_ERR_BAD_DATA_TYPE;
            return;
        }
        oskar_device_check_local_size(location, 0, local_size);
        global_size[0] = oskar_device_global_size(
                (size_t) num_sources, local_size[0]);
        const oskar_Arg args[] = {
                {INT_SZ, &offset_mask},
                {INT_SZ, &num_sources},
                {PTR_SZ, oskar_mem_buffer_const(mask)},
                {INT_SZ, &offset_out},
                {PTR_SZ, oskar_mem_buffer(data)}
        };
        oskar_device_launch_kernel(k, location, 1, local_size, global_size,
                sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status);
    }
}
예제 #9
0
void oskar_dftw(
        int normalise,
        int num_in,
        double wavenumber,
        const oskar_Mem* weights_in,
        const oskar_Mem* x_in,
        const oskar_Mem* y_in,
        const oskar_Mem* z_in,
        int offset_coord_out,
        int num_out,
        const oskar_Mem* x_out,
        const oskar_Mem* y_out,
        const oskar_Mem* z_out,
        const oskar_Mem* data,
        int offset_out,
        oskar_Mem* output,
        int* status)
{
    if (*status) return;
    const int location = oskar_mem_location(output);
    const int type = oskar_mem_precision(output);
    const int is_dbl = oskar_mem_is_double(output);
    const int is_3d = (z_in != NULL && z_out != NULL);
    const int is_data = (data != NULL);
    const int is_matrix = oskar_mem_is_matrix(output);
    if (!oskar_mem_is_complex(output) || !oskar_mem_is_complex(weights_in) ||
            oskar_mem_is_matrix(weights_in))
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    if (oskar_mem_location(weights_in) != location ||
            oskar_mem_location(x_in) != location ||
            oskar_mem_location(y_in) != location ||
            oskar_mem_location(x_out) != location ||
            oskar_mem_location(y_out) != location)
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }
    if (oskar_mem_precision(weights_in) != type ||
            oskar_mem_type(x_in) != type ||
            oskar_mem_type(y_in) != type ||
            oskar_mem_type(x_out) != type ||
            oskar_mem_type(y_out) != type)
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (is_data)
    {
        if (oskar_mem_location(data) != location)
        {
            *status = OSKAR_ERR_LOCATION_MISMATCH;
            return;
        }
        if (!oskar_mem_is_complex(data) ||
                oskar_mem_type(data) != oskar_mem_type(output) ||
                oskar_mem_precision(data) != type)
        {
            *status = OSKAR_ERR_TYPE_MISMATCH;
            return;
        }
    }
    if (is_3d)
    {
        if (oskar_mem_location(z_in) != location ||
                oskar_mem_location(z_out) != location)
        {
            *status = OSKAR_ERR_LOCATION_MISMATCH;
            return;
        }
        if (oskar_mem_type(z_in) != type || oskar_mem_type(z_out) != type)
        {
            *status = OSKAR_ERR_TYPE_MISMATCH;
            return;
        }
    }
    oskar_mem_ensure(output, (size_t) offset_out + num_out, status);
    if (*status) return;
    if (location == OSKAR_CPU)
    {
        if (is_data)
        {
            if (is_matrix)
            {
                if (is_3d)
                {
                    if (is_dbl)
                        dftw_m2m_3d_double(num_in, wavenumber,
                                oskar_mem_double2_const(weights_in, status),
                                oskar_mem_double_const(x_in, status),
                                oskar_mem_double_const(y_in, status),
                                oskar_mem_double_const(z_in, status),
                                offset_coord_out, num_out,
                                oskar_mem_double_const(x_out, status),
                                oskar_mem_double_const(y_out, status),
                                oskar_mem_double_const(z_out, status),
                                oskar_mem_double4c_const(data, status),
                                offset_out,
                                oskar_mem_double4c(output, status), 0);
                    else
                        dftw_m2m_3d_float(num_in, (float)wavenumber,
                                oskar_mem_float2_const(weights_in, status),
                                oskar_mem_float_const(x_in, status),
                                oskar_mem_float_const(y_in, status),
                                oskar_mem_float_const(z_in, status),
                                offset_coord_out, num_out,
                                oskar_mem_float_const(x_out, status),
                                oskar_mem_float_const(y_out, status),
                                oskar_mem_float_const(z_out, status),
                                oskar_mem_float4c_const(data, status),
                                offset_out,
                                oskar_mem_float4c(output, status), 0);
                }
                else
                {
                    if (is_dbl)
                        dftw_m2m_2d_double(num_in, wavenumber,
                                oskar_mem_double2_const(weights_in, status),
                                oskar_mem_double_const(x_in, status),
                                oskar_mem_double_const(y_in, status), 0,
                                offset_coord_out, num_out,
                                oskar_mem_double_const(x_out, status),
                                oskar_mem_double_const(y_out, status), 0,
                                oskar_mem_double4c_const(data, status),
                                offset_out,
                                oskar_mem_double4c(output, status), 0);
                    else
                        dftw_m2m_2d_float(num_in, (float)wavenumber,
                                oskar_mem_float2_const(weights_in, status),
                                oskar_mem_float_const(x_in, status),
                                oskar_mem_float_const(y_in, status), 0,
                                offset_coord_out, num_out,
                                oskar_mem_float_const(x_out, status),
                                oskar_mem_float_const(y_out, status), 0,
                                oskar_mem_float4c_const(data, status),
                                offset_out,
                                oskar_mem_float4c(output, status), 0);
                }
            }
            else
            {
                if (is_3d)
                {
                    if (is_dbl)
                        dftw_c2c_3d_double(num_in, wavenumber,
                                oskar_mem_double2_const(weights_in, status),
                                oskar_mem_double_const(x_in, status),
                                oskar_mem_double_const(y_in, status),
                                oskar_mem_double_const(z_in, status),
                                offset_coord_out, num_out,
                                oskar_mem_double_const(x_out, status),
                                oskar_mem_double_const(y_out, status),
                                oskar_mem_double_const(z_out, status),
                                oskar_mem_double2_const(data, status),
                                offset_out,
                                oskar_mem_double2(output, status), 0);
                    else
                        dftw_c2c_3d_float(num_in, (float)wavenumber,
                                oskar_mem_float2_const(weights_in, status),
                                oskar_mem_float_const(x_in, status),
                                oskar_mem_float_const(y_in, status),
                                oskar_mem_float_const(z_in, status),
                                offset_coord_out, num_out,
                                oskar_mem_float_const(x_out, status),
                                oskar_mem_float_const(y_out, status),
                                oskar_mem_float_const(z_out, status),
                                oskar_mem_float2_const(data, status),
                                offset_out,
                                oskar_mem_float2(output, status), 0);
                }
                else
                {
                    if (is_dbl)
                        dftw_c2c_2d_double(num_in, wavenumber,
                                oskar_mem_double2_const(weights_in, status),
                                oskar_mem_double_const(x_in, status),
                                oskar_mem_double_const(y_in, status), 0,
                                offset_coord_out, num_out,
                                oskar_mem_double_const(x_out, status),
                                oskar_mem_double_const(y_out, status), 0,
                                oskar_mem_double2_const(data, status),
                                offset_out,
                                oskar_mem_double2(output, status), 0);
                    else
                        dftw_c2c_2d_float(num_in, (float)wavenumber,
                                oskar_mem_float2_const(weights_in, status),
                                oskar_mem_float_const(x_in, status),
                                oskar_mem_float_const(y_in, status), 0,
                                offset_coord_out, num_out,
                                oskar_mem_float_const(x_out, status),
                                oskar_mem_float_const(y_out, status), 0,
                                oskar_mem_float2_const(data, status),
                                offset_out,
                                oskar_mem_float2(output, status), 0);
                }
            }
        }
        else
        {
            if (is_3d)
            {
                if (is_dbl)
                    dftw_o2c_3d_double(num_in, wavenumber,
                            oskar_mem_double2_const(weights_in, status),
                            oskar_mem_double_const(x_in, status),
                            oskar_mem_double_const(y_in, status),
                            oskar_mem_double_const(z_in, status),
                            offset_coord_out, num_out,
                            oskar_mem_double_const(x_out, status),
                            oskar_mem_double_const(y_out, status),
                            oskar_mem_double_const(z_out, status),
                            0, offset_out,
                            oskar_mem_double2(output, status), 0);
                else
                    dftw_o2c_3d_float(num_in, (float)wavenumber,
                            oskar_mem_float2_const(weights_in, status),
                            oskar_mem_float_const(x_in, status),
                            oskar_mem_float_const(y_in, status),
                            oskar_mem_float_const(z_in, status),
                            offset_coord_out, num_out,
                            oskar_mem_float_const(x_out, status),
                            oskar_mem_float_const(y_out, status),
                            oskar_mem_float_const(z_out, status),
                            0, offset_out,
                            oskar_mem_float2(output, status), 0);
            }
            else
            {
                if (is_dbl)
                    dftw_o2c_2d_double(num_in, wavenumber,
                            oskar_mem_double2_const(weights_in, status),
                            oskar_mem_double_const(x_in, status),
                            oskar_mem_double_const(y_in, status), 0,
                            offset_coord_out, num_out,
                            oskar_mem_double_const(x_out, status),
                            oskar_mem_double_const(y_out, status), 0,
                            0, offset_out,
                            oskar_mem_double2(output, status), 0);
                else
                    dftw_o2c_2d_float(num_in, (float)wavenumber,
                            oskar_mem_float2_const(weights_in, status),
                            oskar_mem_float_const(x_in, status),
                            oskar_mem_float_const(y_in, status), 0,
                            offset_coord_out, num_out,
                            oskar_mem_float_const(x_out, status),
                            oskar_mem_float_const(y_out, status), 0,
                            0, offset_out,
                            oskar_mem_float2(output, status), 0);
            }
        }
    }
    else
    {
        size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1};
        const void* np = 0;
        const char* k = 0;
        int max_in_chunk;
        float wavenumber_f = (float) wavenumber;

        /* Select the kernel. */
        switch (is_dbl * DBL | is_3d * D3 | is_data * DAT | is_matrix * MAT)
        {
        case D2 | FLT:             k = "dftw_o2c_2d_float";  break;
        case D2 | DBL:             k = "dftw_o2c_2d_double"; break;
        case D3 | FLT:             k = "dftw_o2c_3d_float";  break;
        case D3 | DBL:             k = "dftw_o2c_3d_double"; break;
        case D2 | FLT | DAT:       k = "dftw_c2c_2d_float";  break;
        case D2 | DBL | DAT:       k = "dftw_c2c_2d_double"; break;
        case D3 | FLT | DAT:       k = "dftw_c2c_3d_float";  break;
        case D3 | DBL | DAT:       k = "dftw_c2c_3d_double"; break;
        case D2 | FLT | DAT | MAT: k = "dftw_m2m_2d_float";  break;
        case D2 | DBL | DAT | MAT: k = "dftw_m2m_2d_double"; break;
        case D3 | FLT | DAT | MAT: k = "dftw_m2m_3d_float";  break;
        case D3 | DBL | DAT | MAT: k = "dftw_m2m_3d_double"; break;
        default:
            *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE;
            return;
        }
        if (oskar_device_is_nv(location))
            local_size[0] = (size_t) get_block_size(num_out);
        oskar_device_check_local_size(location, 0, local_size);
        global_size[0] = oskar_device_global_size(
                (size_t) num_out, local_size[0]);

        /* max_in_chunk must be multiple of 16. */
        max_in_chunk = is_3d ? (is_dbl ? 384 : 800) : (is_dbl ? 448 : 896);
        if (is_data && is_3d && !is_dbl) max_in_chunk = 768;
        const size_t element_size = is_dbl ? sizeof(double) : sizeof(float);
        const size_t local_mem_size = max_in_chunk * element_size;
        const size_t arg_size_local[] = {
                2 * local_mem_size, 2 * local_mem_size,
                (is_3d ? local_mem_size : 0)
        };

        /* Set kernel arguments. */
        const oskar_Arg args[] = {
                {INT_SZ, &num_in},
                {is_dbl ? DBL_SZ : FLT_SZ,
                        is_dbl ? (void*)&wavenumber : (void*)&wavenumber_f},
                {PTR_SZ, oskar_mem_buffer_const(weights_in)},
                {PTR_SZ, oskar_mem_buffer_const(x_in)},
                {PTR_SZ, oskar_mem_buffer_const(y_in)},
                {PTR_SZ, is_3d ? oskar_mem_buffer_const(z_in) : &np},
                {INT_SZ, &offset_coord_out},
                {INT_SZ, &num_out},
                {PTR_SZ, oskar_mem_buffer_const(x_out)},
                {PTR_SZ, oskar_mem_buffer_const(y_out)},
                {PTR_SZ, is_3d ? oskar_mem_buffer_const(z_out) : &np},
                {PTR_SZ, is_data ? oskar_mem_buffer_const(data) : &np},
                {INT_SZ, &offset_out},
                {PTR_SZ, oskar_mem_buffer(output)},
                {INT_SZ, &max_in_chunk}
        };
        oskar_device_launch_kernel(k, location, 1, local_size, global_size,
                sizeof(args) / sizeof(oskar_Arg), args,
                sizeof(arg_size_local) / sizeof(size_t), arg_size_local,
                status);
    }
    if (normalise)
        oskar_mem_scale_real(output, 1. / num_in, offset_out, num_out, status);
}
예제 #10
0
oskar_Sky* oskar_sky_from_image(int precision, const oskar_Mem* image,
        int image_width, int image_height, double image_ra_deg,
        double image_dec_deg, double image_cellsize_deg, double image_freq_hz,
        double spectral_index, int* status)
{
    int i, type, x, y;
    double crval[2], crpix[2], cdelt[2], val;
    oskar_Sky* sky;

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

    /* Check the image size is even. */
    if ((image_width % 2) || (image_height % 2))
    {
        *status = OSKAR_ERR_INVALID_ARGUMENT;
        return 0;
    }

    /* Get reference pixels and reference values in radians. */
    crpix[0] = image_width / 2 + 1;
    crpix[1] = image_height / 2 + 1;
    crval[0] = image_ra_deg * M_PI / 180.0;
    crval[1] = image_dec_deg * M_PI / 180.0;

    /* Compute sine of pixel deltas for inverse orthographic projection. */
    cdelt[0] = -sin(image_cellsize_deg * M_PI / 180.0);
    cdelt[1] = -cdelt[0];

    /* Create a sky model. */
    sky = oskar_sky_create(precision, OSKAR_CPU, 0, status);

    /* Store the image pixels. */
    type = oskar_mem_precision(image);
    if (type == OSKAR_SINGLE)
    {
        const float *img = oskar_mem_float_const(image, status);
        for (y = 0, i = 0; y < image_height; ++y)
        {
            for (x = 0; x < image_width; ++x)
            {
                /* Check pixel value. */
                val = (double) (img[image_width * y + x]);
                if (val == 0.0)
                    continue;

                set_pixel(sky, i++, x, y, val, crval, crpix, cdelt,
                        image_freq_hz, spectral_index, status);
            }
        }
    }
    else
    {
        const double *img = oskar_mem_double_const(image, status);
        for (y = 0, i = 0; y < image_height; ++y)
        {
            for (x = 0; x < image_width; ++x)
            {
                /* Check pixel value. */
                val = img[image_width * y + x];
                if (val == 0.0)
                    continue;

                set_pixel(sky, i++, x, y, val, crval, crpix, cdelt,
                        image_freq_hz, spectral_index, status);
            }
        }
    }

    /* Return the sky model. */
    oskar_sky_resize(sky, i, status);
    return sky;
}
/* Wrapper. */
void oskar_convert_ludwig3_to_theta_phi_components(oskar_Mem* vec,
        int offset, int stride, int num_points, const oskar_Mem* phi,
        int* status)
{
    int type, location;

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

    /* Check that the vector component data is in matrix form. */
    if (!oskar_mem_is_matrix(vec))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }

    /* Get data type and location. */
    type = oskar_mem_type(phi);
    location = oskar_mem_location(phi);

    /* Convert vector representation from Ludwig-3 to spherical. */
    if (type == OSKAR_SINGLE)
    {
        float2 *h_theta, *v_phi;
        const float *phi_;
        h_theta = oskar_mem_float2(vec, status) + offset;
        v_phi = oskar_mem_float2(vec, status) + offset + 1;
        phi_ = oskar_mem_float_const(phi, status);

        if (location == OSKAR_GPU)
        {
#ifdef OSKAR_HAVE_CUDA
            oskar_convert_ludwig3_to_theta_phi_components_cuda_f(num_points,
                    h_theta, v_phi, phi_, stride);
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
        else if (location == OSKAR_CPU)
        {
            oskar_convert_ludwig3_to_theta_phi_components_f(num_points,
                    h_theta, v_phi, phi_, stride);
        }
    }
    else if (type == OSKAR_DOUBLE)
    {
        double2 *h_theta, *v_phi;
        const double *phi_;
        h_theta = oskar_mem_double2(vec, status) + offset;
        v_phi = oskar_mem_double2(vec, status) + offset + 1;
        phi_ = oskar_mem_double_const(phi, status);

        if (location == OSKAR_GPU)
        {
#ifdef OSKAR_HAVE_CUDA
            oskar_convert_ludwig3_to_theta_phi_components_cuda_d(num_points,
                    h_theta, v_phi, phi_, stride);
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
        else if (location == OSKAR_CPU)
        {
            oskar_convert_ludwig3_to_theta_phi_components_d(num_points,
                    h_theta, v_phi, phi_, stride);
        }
    }
    else
        *status = OSKAR_ERR_BAD_DATA_TYPE;
}
    }

    /* Check numbers are the same, to appropriate precision. */
    if (prec_approx == OSKAR_SINGLE && prec_accurate == OSKAR_SINGLE)
    {
        const float *approx, *accurate;
        approx = oskar_mem_float_const(app_ptr, status);
        accurate = oskar_mem_float_const(acc_ptr, status);
        CHECK_ELEMENTS(1e-5)
    }
    else if (prec_approx == OSKAR_DOUBLE && prec_accurate == OSKAR_SINGLE)
    {
        const double *approx;
        const float *accurate;
        approx = oskar_mem_double_const(app_ptr, status);
        accurate = oskar_mem_float_const(acc_ptr, status);
        CHECK_ELEMENTS(1e-5);
    }
    else if (prec_approx == OSKAR_SINGLE && prec_accurate == OSKAR_DOUBLE)
    {
        const float *approx;
        const double *accurate;
        approx = oskar_mem_float_const(app_ptr, status);
        accurate = oskar_mem_double_const(acc_ptr, status);
        CHECK_ELEMENTS(1e-5);
    }
    else if (prec_approx == OSKAR_DOUBLE && prec_accurate == OSKAR_DOUBLE)
    {
        const double *approx, *accurate;
        approx = oskar_mem_double_const(app_ptr, status);
        accurate = oskar_mem_double_const(acc_ptr, status);
int main(int argc, char** argv)
{
    // ===== Declare options ==================================================
    oskar::OptionParser opt("oskar_vis_to_ascii_table", oskar_version_string());
    opt.set_description("Converts an OSKAR visibility binary file to an ASCII "
            "table format with the following columns:\n "
            "[1] index, [2] baseline-uu, [3] baseline-vv, [4] baseline-ww "
            "[5] Real, [6] Imag. "
            "The table is written out in baseline-time order where baseline "
            "is the fastest varying dimension");
    opt.add_required("OSKAR vis file");
    opt.add_optional("output file name");
    opt.add_flag("-c", "Channel index to write to file. (default = 0)", 1, "0",
            false, "--channel");
    opt.add_flag("-p", "Polarisation ID to write to file. (default = 0) "
            "(0=I, 1=Q, 2=U, 3=V, 4=XX, 5=XY, 6=YX, 7=YY)",
            1, "0", false, "--polarisation");
    opt.add_flag("-t", "Time index to write to file. (default = all)", 1, "",
            false, "--time");
    opt.add_flag("-w", "Output baseline coordinates in wavelengths. "
            "(default = metres)", false, "--baseline_wavelengths");
    opt.add_flag("-h", "Write a summary header in the ASCII table. ");
    opt.add_flag("-v", "Verbose mode.");
    opt.add_flag("--csv", "Write in CSV format");
    opt.add_flag("-s", "Write output table to standard output instead of to file.",
            false, "--stdout");
    if (!opt.check_options(argc, argv)) return EXIT_FAILURE;

    // ===== Read options ====================================================
    const char* vis_file = opt.get_arg(0);
    std::string txt_file;
    if (opt.num_args() == 2)
        txt_file = std::string(opt.get_arg(1));
    else {
        txt_file = std::string(vis_file) + ".txt";
    }
    int c = 0, p = 0, t = -1;
    if (opt.is_set("-c")) c = opt.get_int("-c");
    if (opt.is_set("-p")) p = opt.get_int("-p");
    if (opt.is_set("-t")) t = opt.get_int("-t");
    bool metres = !opt.is_set("-w");
    bool write_header = opt.is_set("-h");
    bool csv = opt.is_set("--csv");
    bool verbose = opt.is_set("-v");

    // ===== Write table ======================================================
    int status = 0;
    oskar_Binary* h = oskar_binary_create(vis_file, 'r', &status);
    oskar_Vis* vis = oskar_vis_read(h, &status);
    if (status)
    {
        fprintf(stderr, "ERROR: Unable to read specified visibility file: %s\n",
                vis_file);
        oskar_vis_free(vis, &status);
        oskar_binary_free(h);
        return status;
    }
    oskar_binary_free(h);

    int num_chan = oskar_vis_num_channels(vis);
    int num_times = oskar_vis_num_times(vis);
    int num_baselines = oskar_vis_num_baselines(vis);
    int num_pol = oskar_vis_num_pols(vis);
    int num_stations = oskar_vis_num_stations(vis);
    int total_vis = num_chan * num_times * num_baselines * num_pol;
    double freq_start_hz = oskar_vis_freq_start_hz(vis);
    double freq_inc_hz = oskar_vis_freq_inc_hz(vis);
    double freq_hz = freq_start_hz + c * freq_inc_hz;
    double lambda_m = 299792458.0 / freq_hz;

    if (t != -1 && t > num_times-1) {
        fprintf(stderr, "ERROR: Time index out of range.\n");
        return EXIT_FAILURE;
    }
    if (c > num_chan-1) {
        fprintf(stderr, "ERROR: Channel index out of range.\n");
        return EXIT_FAILURE;
    }


    FILE* out;
    if (!opt.is_set("-s")) {
        out = fopen(txt_file.c_str(), "w");
        if (out == NULL) return EXIT_FAILURE;
    }
    else {
        out = stdout;
    }

    const oskar_Mem* uu = oskar_vis_baseline_uu_metres_const(vis);
    const oskar_Mem* vv = oskar_vis_baseline_vv_metres_const(vis);
    const oskar_Mem* ww = oskar_vis_baseline_ww_metres_const(vis);
    const oskar_Mem* amp = oskar_vis_amplitude_const(vis);
    // amplitudes dims: channel x times x baselines x pol
    int amp_offset = c * num_times * num_baselines;
    if (t != -1) amp_offset += t * num_baselines;
    // baseline dims: times x baselines
    int baseline_offset = 0;
    if (t != -1) baseline_offset = t * num_baselines;
    int type = oskar_mem_type(uu);

    int num_vis_out = num_baselines;
    if (t == -1) num_vis_out *= num_times;

    if (verbose) {
        write_header_(stdout, total_vis, num_chan, num_times, num_baselines,
                num_pol, num_stations, num_vis_out, c, freq_hz, lambda_m, p, t,
                metres);
#if 0
        fprintf(stdout, "amp_offset      = %i\n", amp_offset);
        fprintf(stdout, "baseline_offset = %i\n", baseline_offset);
#endif
    }

    // Write header if specified
    if (write_header)
    {
        write_header_(out, total_vis, num_chan, num_times, num_baselines,
                num_pol, num_stations, num_vis_out, c, freq_hz, lambda_m, p, t,
                metres);
        char pre = '#';
        fprintf(out, "%c\n", pre);
        fprintf(out, "%c %s %-14s %-15s %-15s %-23s %-15s\n",
                pre, "Idx", " uu", "  vv", "  ww", "  Amp. Re.", "  Amp. Im.");
    }

    if (type == OSKAR_DOUBLE)
    {
        const double* uu_ = oskar_mem_double_const(uu, &status);
        const double* vv_ = oskar_mem_double_const(vv, &status);
        const double* ww_ = oskar_mem_double_const(ww, &status);
        const double4c* amp_ = oskar_mem_double4c_const(amp, &status);
        int aIdx = amp_offset;
        int bIdx = baseline_offset;
        for (int i = 0; i < num_vis_out; ++i, ++bIdx, ++aIdx)
        {
            double2 a = getPolAmp_<double2, double4c>(amp_[aIdx], p);
            double buu = (metres)? uu_[bIdx] : uu_[bIdx]/lambda_m;
            double bvv = (metres)? vv_[bIdx] : vv_[bIdx]/lambda_m;
            double bww = (metres)? ww_[bIdx] : ww_[bIdx]/lambda_m;
            writeData_<double, double2>(i, buu, bvv, bww, a, csv, out);
        }
    }
    else // OSKAR_SINGLE
    {
        const float* uu_ = oskar_mem_float_const(uu, &status);
        const float* vv_ = oskar_mem_float_const(vv, &status);
        const float* ww_ = oskar_mem_float_const(ww, &status);
        const float4c* amp_ = oskar_mem_float4c_const(amp, &status);
        int aIdx = amp_offset;
        int bIdx = baseline_offset;
        for (int i = 0; i < num_vis_out; ++i, ++bIdx, ++aIdx)
        {
            float2 a = getPolAmp_<float2, float4c>(amp_[aIdx], p);
            float buu = (metres)? uu_[bIdx] : uu_[bIdx]/lambda_m;
            float bvv = (metres)? vv_[bIdx] : vv_[bIdx]/lambda_m;
            float bww = (metres)? ww_[bIdx] : ww_[bIdx]/lambda_m;
            writeData_<float, float2>(i, buu, bvv, bww, a, csv, out);
        }
    }

    fclose(out);
    oskar_vis_free(vis, &status);

    return status;
}
예제 #14
0
void oskar_auto_correlate(oskar_Mem* vis, int n_sources, const oskar_Jones* J,
        const oskar_Sky* sky, int* status)
{
    int jones_type, base_type, location, matrix_type, n_stations;

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

    /* Get the data dimensions. */
    n_stations = oskar_jones_num_stations(J);

    /* Check data locations. */
    location = oskar_sky_mem_location(sky);
    if (oskar_jones_mem_location(J) != location ||
            oskar_mem_location(vis) != location)
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }

    /* Check for consistent data types. */
    jones_type = oskar_jones_type(J);
    base_type = oskar_sky_precision(sky);
    matrix_type = oskar_type_is_matrix(jones_type) &&
            oskar_mem_is_matrix(vis);
    if (oskar_mem_precision(vis) != base_type ||
            oskar_type_precision(jones_type) != base_type)
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (oskar_mem_type(vis) != jones_type)
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }

    /* If neither single or double precision, return error. */
    if (base_type != OSKAR_SINGLE && base_type != OSKAR_DOUBLE)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }

    /* Check the input dimensions. */
    if (oskar_jones_num_sources(J) < n_sources)
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }

    /* Select kernel. */
    if (base_type == OSKAR_DOUBLE)
    {
        const double *I_, *Q_, *U_, *V_;
        I_ = oskar_mem_double_const(oskar_sky_I_const(sky), status);
        Q_ = oskar_mem_double_const(oskar_sky_Q_const(sky), status);
        U_ = oskar_mem_double_const(oskar_sky_U_const(sky), status);
        V_ = oskar_mem_double_const(oskar_sky_V_const(sky), status);

        if (matrix_type)
        {
            double4c *vis_;
            const double4c *J_;
            vis_ = oskar_mem_double4c(vis, status);
            J_   = oskar_jones_double4c_const(J, status);

            if (location == OSKAR_GPU)
            {
#ifdef OSKAR_HAVE_CUDA
                oskar_auto_correlate_cuda_d(n_sources, n_stations,
                        J_, I_, Q_, U_, V_, vis_);
                oskar_device_check_error(status);
#else
                *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
            }
            else /* CPU */
            {
                oskar_auto_correlate_omp_d(n_sources, n_stations,
                        J_, I_, Q_, U_, V_, vis_);
            }
        }
        else /* Scalar version. */
        {
            double2 *vis_;
            const double2 *J_;
            vis_ = oskar_mem_double2(vis, status);
            J_   = oskar_jones_double2_const(J, status);

            if (location == OSKAR_GPU)
            {
#ifdef OSKAR_HAVE_CUDA
                oskar_auto_correlate_scalar_cuda_d(n_sources, n_stations,
                        J_, I_, vis_);
                oskar_device_check_error(status);
#else
                *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
            }
            else /* CPU */
            {
                oskar_auto_correlate_scalar_omp_d(n_sources, n_stations,
                        J_, I_, vis_);
            }
        }
    }
    else /* Single precision. */
    {
        const float *I_, *Q_, *U_, *V_;
        I_ = oskar_mem_float_const(oskar_sky_I_const(sky), status);
        Q_ = oskar_mem_float_const(oskar_sky_Q_const(sky), status);
        U_ = oskar_mem_float_const(oskar_sky_U_const(sky), status);
        V_ = oskar_mem_float_const(oskar_sky_V_const(sky), status);

        if (matrix_type)
        {
            float4c *vis_;
            const float4c *J_;
            vis_ = oskar_mem_float4c(vis, status);
            J_   = oskar_jones_float4c_const(J, status);

            if (location == OSKAR_GPU)
            {
#ifdef OSKAR_HAVE_CUDA
                oskar_auto_correlate_cuda_f(n_sources, n_stations,
                        J_, I_, Q_, U_, V_, vis_);
                oskar_device_check_error(status);
#else
                *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
            }
            else /* CPU */
            {
                oskar_auto_correlate_omp_f(n_sources, n_stations,
                        J_, I_, Q_, U_, V_, vis_);
            }
        }
        else /* Scalar version. */
        {
            float2 *vis_;
            const float2 *J_;
            vis_ = oskar_mem_float2(vis, status);
            J_   = oskar_jones_float2_const(J, status);

            if (location == OSKAR_GPU)
            {
#ifdef OSKAR_HAVE_CUDA
                oskar_auto_correlate_scalar_cuda_f(n_sources, n_stations,
                        J_, I_, vis_);
                oskar_device_check_error(status);
#else
                *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
            }
            else /* CPU */
            {
                oskar_auto_correlate_scalar_omp_f(n_sources, n_stations,
                        J_, I_, vis_);
            }
        }
    }
}
int main(int argc, char** argv)
{
    int status = 0;
    oskar::OptionParser opt("oskar_evaulate_pierce_points",
            oskar_version_string());
    opt.add_required("settings file");
    if (!opt.check_options(argc, argv)) return EXIT_FAILURE;

    const char* settings_file = opt.get_arg();

    // Create the log.
    oskar_Log* log = oskar_log_create(OSKAR_LOG_MESSAGE, OSKAR_LOG_STATUS);
    oskar_log_message(log, 'M', 0, "Running binary %s", argv[0]);

    // Enum values used in writing time-freq data binary files
    enum OSKAR_TIME_FREQ_TAGS
    {
        TIME_IDX       = 0,
        FREQ_IDX       = 1,
        TIME_MJD_UTC   = 2,
        FREQ_HZ        = 3,
        NUM_FIELDS     = 4,
        NUM_FIELD_TAGS = 5,
        HEADER_OFFSET  = 10,
        DATA           = 0,
        DIMS           = 1,
        LABEL          = 2,
        UNITS          = 3,
        GRP            = OSKAR_TAG_GROUP_TIME_FREQ_DATA
    };

    oskar_Settings_old settings;
    oskar_settings_old_load(&settings, log, settings_file, &status);
    oskar_log_set_keep_file(log, settings.sim.keep_log_file);
    if (status) return status;

    oskar_Telescope* tel = oskar_settings_to_telescope(&settings, log, &status);
    oskar_Sky* sky = oskar_settings_to_sky(&settings, log, &status);

    // FIXME remove this restriction ... (see evaluate Z)
    if (settings.ionosphere.num_TID_screens != 1)
        return OSKAR_ERR_SETUP_FAIL;

    int type = settings.sim.double_precision ? OSKAR_DOUBLE : OSKAR_SINGLE;
    int loc = OSKAR_CPU;

    int num_sources = oskar_sky_num_sources(sky);
    oskar_Mem *hor_x, *hor_y, *hor_z;
    hor_x = oskar_mem_create(type, loc, num_sources, &status);
    hor_y = oskar_mem_create(type, loc, num_sources, &status);
    hor_z = oskar_mem_create(type, loc, num_sources, &status);

    oskar_Mem *pp_lon, *pp_lat, *pp_rel_path;
    int num_stations = oskar_telescope_num_stations(tel);

    int num_pp = num_stations * num_sources;
    pp_lon = oskar_mem_create(type, loc, num_pp, &status);
    pp_lat = oskar_mem_create(type, loc, num_pp, &status);
    pp_rel_path = oskar_mem_create(type, loc, num_pp, &status);

    // Pierce points for one station (non-owned oskar_Mem pointers)
    oskar_Mem *pp_st_lon, *pp_st_lat, *pp_st_rel_path;
    pp_st_lon = oskar_mem_create_alias(0, 0, 0, &status);
    pp_st_lat = oskar_mem_create_alias(0, 0, 0, &status);
    pp_st_rel_path = oskar_mem_create_alias(0, 0, 0, &status);

    int num_times = settings.obs.num_time_steps;
    double obs_start_mjd_utc = settings.obs.start_mjd_utc;
    double dt_dump = settings.obs.dt_dump_days;

    // Binary file meta-data
    std::string label1 = "pp_lon";
    std::string label2 = "pp_lat";
    std::string label3 = "pp_path";
    std::string units  = "radians";
    std::string units2 = "";
    oskar_Mem *dims = oskar_mem_create(OSKAR_INT, loc, 2, &status);
    /* FIXME is this the correct dimension order ?
     * FIXME get the MATLAB reader to respect dimension ordering */
    oskar_mem_int(dims, &status)[0] = num_sources;
    oskar_mem_int(dims, &status)[1] = num_stations;

    const char* filename = settings.ionosphere.pierce_points.filename;
    oskar_Binary* h = oskar_binary_create(filename, 'w', &status);

    double screen_height_m = settings.ionosphere.TID->height_km * 1000.0;

//    printf("Number of times    = %i\n", num_times);
//    printf("Number of stations = %i\n", num_stations);

    void *x_, *y_, *z_;
    x_ = oskar_mem_void(oskar_telescope_station_true_x_offset_ecef_metres(tel));
    y_ = oskar_mem_void(oskar_telescope_station_true_y_offset_ecef_metres(tel));
    z_ = oskar_mem_void(oskar_telescope_station_true_z_offset_ecef_metres(tel));

    for (int t = 0; t < num_times; ++t)
    {
        double t_dump = obs_start_mjd_utc + t * dt_dump; // MJD UTC
        double gast = oskar_convert_mjd_to_gast_fast(t_dump + dt_dump / 2.0);

        for (int i = 0; i < num_stations; ++i)
        {
            const oskar_Station* station =
                    oskar_telescope_station_const(tel, i);
            double lon = oskar_station_lon_rad(station);
            double lat = oskar_station_lat_rad(station);
            double alt = oskar_station_alt_metres(station);
            double x_ecef, y_ecef, z_ecef, x_offset, y_offset, z_offset;

            if (type == OSKAR_DOUBLE)
            {
                x_offset = ((double*)x_)[i];
                y_offset = ((double*)y_)[i];
                z_offset = ((double*)z_)[i];
            }
            else
            {
                x_offset = (double)((float*)x_)[i];
                y_offset = (double)((float*)y_)[i];
                z_offset = (double)((float*)z_)[i];
            }

            oskar_convert_offset_ecef_to_ecef(1, &x_offset, &y_offset,
                    &z_offset, lon, lat, alt, &x_ecef, &y_ecef, &z_ecef);
            double last = gast + lon;

            if (type == OSKAR_DOUBLE)
            {
                oskar_convert_apparent_ra_dec_to_enu_directions_d(num_sources,
                        oskar_mem_double_const(oskar_sky_ra_rad_const(sky), &status),
                        oskar_mem_double_const(oskar_sky_dec_rad_const(sky), &status),
                        last, lat, oskar_mem_double(hor_x, &status),
                        oskar_mem_double(hor_y, &status),
                        oskar_mem_double(hor_z, &status));
            }
            else
            {
                oskar_convert_apparent_ra_dec_to_enu_directions_f(num_sources,
                        oskar_mem_float_const(oskar_sky_ra_rad_const(sky), &status),
                        oskar_mem_float_const(oskar_sky_dec_rad_const(sky), &status),
                        last, lat, oskar_mem_float(hor_x, &status),
                        oskar_mem_float(hor_y, &status),
                        oskar_mem_float(hor_z, &status));
            }

            int offset = i * num_sources;
            oskar_mem_set_alias(pp_st_lon, pp_lon, offset, num_sources,
                    &status);
            oskar_mem_set_alias(pp_st_lat, pp_lat, offset, num_sources,
                    &status);
            oskar_mem_set_alias(pp_st_rel_path, pp_rel_path, offset,
                    num_sources, &status);
            oskar_evaluate_pierce_points(pp_st_lon, pp_st_lat, pp_st_rel_path,
                    x_ecef, y_ecef, z_ecef, screen_height_m,
                    num_sources, hor_x, hor_y, hor_z, &status);
        } // Loop over stations.

        if (status != 0)
            continue;

        int index = t; // could be = (num_times * f) + t if we have frequency data
        int num_fields = 3;
        int num_field_tags = 4;
        double freq_hz = 0.0;
        int freq_idx = 0;

        // Write the header TAGS
        oskar_binary_write_int(h, GRP, TIME_IDX, index, t, &status);
        oskar_binary_write_double(h, GRP, FREQ_IDX, index, freq_idx, &status);
        oskar_binary_write_double(h, GRP, TIME_MJD_UTC, index, t_dump, &status);
        oskar_binary_write_double(h, GRP, FREQ_HZ, index, freq_hz, &status);
        oskar_binary_write_int(h, GRP, NUM_FIELDS, index, num_fields, &status);
        oskar_binary_write_int(h, GRP, NUM_FIELD_TAGS, index, num_field_tags,
                &status);

        // Write data TAGS (fields)
        int field, tagID;
        field = 0;
        tagID = HEADER_OFFSET + (num_field_tags * field);
        oskar_binary_write_mem(h, pp_lon, GRP, tagID + DATA,
                index, 0, &status);
        oskar_binary_write_mem(h, dims, GRP, tagID  + DIMS,
                index, 0, &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL,
                index, label1.size()+1, label1.c_str(), &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS,
                index, units.size()+1, units.c_str(), &status);
        field = 1;
        tagID = HEADER_OFFSET + (num_field_tags * field);
        oskar_binary_write_mem(h, pp_lat, GRP, tagID + DATA,
                index, 0, &status);
        oskar_binary_write_mem(h, dims, GRP, tagID  + DIMS,
                index, 0, &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL,
                index, label2.size()+1, label2.c_str(), &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS,
                index, units.size()+1, units.c_str(), &status);
        field = 2;
        tagID = HEADER_OFFSET + (num_field_tags * field);
        oskar_binary_write_mem(h, pp_rel_path, GRP, tagID + DATA,
                index, 0, &status);
        oskar_binary_write_mem(h, dims, GRP, tagID  + DIMS,
                index, 0, &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL,
                index, label3.size()+1, label3.c_str(), &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS,
                index, units2.size()+1, units2.c_str(), &status);
    } // Loop over times

    // Close the OSKAR binary file.
    oskar_binary_free(h);

    // clean up memory
    oskar_mem_free(hor_x, &status);
    oskar_mem_free(hor_y, &status);
    oskar_mem_free(hor_z, &status);
    oskar_mem_free(pp_lon, &status);
    oskar_mem_free(pp_lat, &status);
    oskar_mem_free(pp_rel_path, &status);
    oskar_mem_free(pp_st_lon, &status);
    oskar_mem_free(pp_st_lat, &status);
    oskar_mem_free(pp_st_rel_path, &status);
    oskar_mem_free(dims, &status);
    oskar_telescope_free(tel, &status);
    oskar_sky_free(sky, &status);

    // Check for errors.
    if (status)
        oskar_log_error(log, "Run failed: %s.", oskar_get_error_string(status));
    oskar_log_free(log);

    return status;
}
/* Wrapper. */
void oskar_sky_scale_flux_with_frequency(oskar_Sky* sky, double frequency,
        int* status)
{
    int type, location, num_sources;

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

    /* Get the type, location and dimensions. */
    type = oskar_sky_precision(sky);
    location = oskar_sky_mem_location(sky);
    num_sources = oskar_sky_num_sources(sky);

    /* Scale the flux values. */
    if (location == OSKAR_CPU)
    {
        if (type == OSKAR_SINGLE)
            oskar_sky_scale_flux_with_frequency_f(num_sources, frequency,
                    oskar_mem_float(oskar_sky_I(sky), status),
                    oskar_mem_float(oskar_sky_Q(sky), status),
                    oskar_mem_float(oskar_sky_U(sky), status),
                    oskar_mem_float(oskar_sky_V(sky), status),
                    oskar_mem_float(oskar_sky_reference_freq_hz(sky), status),
                    oskar_mem_float_const(
                            oskar_sky_spectral_index_const(sky), status),
                    oskar_mem_float_const(
                            oskar_sky_rotation_measure_rad_const(sky), status));
        else if (type == OSKAR_DOUBLE)
            oskar_sky_scale_flux_with_frequency_d(num_sources, frequency,
                    oskar_mem_double(oskar_sky_I(sky), status),
                    oskar_mem_double(oskar_sky_Q(sky), status),
                    oskar_mem_double(oskar_sky_U(sky), status),
                    oskar_mem_double(oskar_sky_V(sky), status),
                    oskar_mem_double(oskar_sky_reference_freq_hz(sky), status),
                    oskar_mem_double_const(
                            oskar_sky_spectral_index_const(sky), status),
                    oskar_mem_double_const(
                            oskar_sky_rotation_measure_rad_const(sky), status));
        else
            *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
    else if (location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        if (type == OSKAR_SINGLE)
            oskar_sky_scale_flux_with_frequency_cuda_f(num_sources, frequency,
                    oskar_mem_float(oskar_sky_I(sky), status),
                    oskar_mem_float(oskar_sky_Q(sky), status),
                    oskar_mem_float(oskar_sky_U(sky), status),
                    oskar_mem_float(oskar_sky_V(sky), status),
                    oskar_mem_float(oskar_sky_reference_freq_hz(sky), status),
                    oskar_mem_float_const(
                            oskar_sky_spectral_index_const(sky), status),
                    oskar_mem_float_const(
                            oskar_sky_rotation_measure_rad_const(sky), status));
        else if (type == OSKAR_DOUBLE)
            oskar_sky_scale_flux_with_frequency_cuda_d(num_sources, frequency,
                    oskar_mem_double(oskar_sky_I(sky), status),
                    oskar_mem_double(oskar_sky_Q(sky), status),
                    oskar_mem_double(oskar_sky_U(sky), status),
                    oskar_mem_double(oskar_sky_V(sky), status),
                    oskar_mem_double(oskar_sky_reference_freq_hz(sky), status),
                    oskar_mem_double_const(
                            oskar_sky_spectral_index_const(sky), status),
                    oskar_mem_double_const(
                            oskar_sky_rotation_measure_rad_const(sky), status));
        else
            *status = OSKAR_ERR_BAD_DATA_TYPE;
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else if (location & OSKAR_CL)
    {
#ifdef OSKAR_HAVE_OPENCL
        cl_event event;
        cl_kernel k = 0;
        cl_int error, num;
        cl_uint arg = 0;
        size_t global_size, local_size;
        if (type == OSKAR_DOUBLE)
            k = oskar_cl_kernel("scale_flux_with_frequency_double");
        else if (type == OSKAR_SINGLE)
            k = oskar_cl_kernel("scale_flux_with_frequency_float");
        else
        {
            *status = OSKAR_ERR_BAD_DATA_TYPE;
            return;
        }
        if (!k)
        {
            *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE;
            return;
        }

        /* Set kernel arguments. */
        num = (cl_int) num_sources;
        error = clSetKernelArg(k, arg++, sizeof(cl_int), &num);
        if (type == OSKAR_SINGLE)
        {
            const cl_float freq = (cl_float) frequency;
            error |= clSetKernelArg(k, arg++, sizeof(cl_float), &freq);
        }
        else if (type == OSKAR_DOUBLE)
        {
            const cl_double freq = (cl_double) frequency;
            error |= clSetKernelArg(k, arg++, sizeof(cl_double), &freq);
        }
        error |= clSetKernelArg(k, arg++, sizeof(cl_mem),
                oskar_mem_cl_buffer(oskar_sky_I(sky), status));
        error |= clSetKernelArg(k, arg++, sizeof(cl_mem),
                oskar_mem_cl_buffer(oskar_sky_Q(sky), status));
        error |= clSetKernelArg(k, arg++, sizeof(cl_mem),
                oskar_mem_cl_buffer(oskar_sky_U(sky), status));
        error |= clSetKernelArg(k, arg++, sizeof(cl_mem),
                oskar_mem_cl_buffer(oskar_sky_V(sky), status));
        error |= clSetKernelArg(k, arg++, sizeof(cl_mem),
                oskar_mem_cl_buffer(oskar_sky_reference_freq_hz(sky), status));
        error |= clSetKernelArg(k, arg++, sizeof(cl_mem),
                oskar_mem_cl_buffer_const(oskar_sky_spectral_index_const(sky), status));
        error |= clSetKernelArg(k, arg++, sizeof(cl_mem),
                oskar_mem_cl_buffer_const(oskar_sky_rotation_measure_rad_const(sky), status));
        if (error != CL_SUCCESS)
        {
            *status = OSKAR_ERR_INVALID_ARGUMENT;
            return;
        }

        /* Launch kernel on current command queue. */
        local_size = oskar_cl_is_gpu() ? 256 : 128;
        global_size = ((num + local_size - 1) / local_size) * local_size;
        error = clEnqueueNDRangeKernel(oskar_cl_command_queue(), k, 1, NULL,
                &global_size, &local_size, 0, NULL, &event);
        if (error != CL_SUCCESS)
            *status = OSKAR_ERR_KERNEL_LAUNCH_FAILURE;
#else
        *status = OSKAR_ERR_OPENCL_NOT_AVAILABLE;
#endif
    }
    else
        *status = OSKAR_ERR_BAD_LOCATION;
}
예제 #17
0
void oskar_gaussian_circular(int num_points,
        const oskar_Mem* l, const oskar_Mem* m, double std,
        oskar_Mem* out, int* status)
{
    if (*status) return;
    const int location = oskar_mem_location(out);
    const double inv_2_var = 1.0 / (2.0 * std * std);
    const float inv_2_var_f = (float)inv_2_var;
    if (oskar_mem_precision(out) != oskar_mem_type(l) ||
            oskar_mem_precision(out) != oskar_mem_type(m))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (location != oskar_mem_location(l) || location != oskar_mem_location(m))
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }
    if ((int)oskar_mem_length(l) < num_points ||
            (int)oskar_mem_length(m) < num_points)
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }
    oskar_mem_ensure(out, num_points, status);
    if (*status) return;
    if (location == OSKAR_CPU)
    {
        switch (oskar_mem_type(out))
        {
        case OSKAR_SINGLE_COMPLEX:
            gaussian_circular_complex_f(num_points,
                    oskar_mem_float_const(l, status),
                    oskar_mem_float_const(m, status), inv_2_var_f,
                    oskar_mem_float2(out, status));
            break;
        case OSKAR_DOUBLE_COMPLEX:
            gaussian_circular_complex_d(num_points,
                    oskar_mem_double_const(l, status),
                    oskar_mem_double_const(m, status), inv_2_var,
                    oskar_mem_double2(out, status));
            break;
        case OSKAR_SINGLE_COMPLEX_MATRIX:
            gaussian_circular_matrix_f(num_points,
                    oskar_mem_float_const(l, status),
                    oskar_mem_float_const(m, status), inv_2_var_f,
                    oskar_mem_float4c(out, status));
            break;
        case OSKAR_DOUBLE_COMPLEX_MATRIX:
            gaussian_circular_matrix_d(num_points,
                    oskar_mem_double_const(l, status),
                    oskar_mem_double_const(m, status), inv_2_var,
                    oskar_mem_double4c(out, status));
            break;
        default:
            *status = OSKAR_ERR_BAD_DATA_TYPE;
            break;
        }
    }
    else
    {
        size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1};
        const char* k = 0;
        const int is_dbl = oskar_mem_is_double(out);
        switch (oskar_mem_type(out))
        {
        case OSKAR_SINGLE_COMPLEX:
            k = "gaussian_circular_complex_float"; break;
        case OSKAR_DOUBLE_COMPLEX:
            k = "gaussian_circular_complex_double"; break;
        case OSKAR_SINGLE_COMPLEX_MATRIX:
            k = "gaussian_circular_matrix_float"; break;
        case OSKAR_DOUBLE_COMPLEX_MATRIX:
            k = "gaussian_circular_matrix_double"; break;
        default:
            *status = OSKAR_ERR_BAD_DATA_TYPE;
            return;
        }
        oskar_device_check_local_size(location, 0, local_size);
        global_size[0] = oskar_device_global_size(
                (size_t) num_points, local_size[0]);
        const oskar_Arg args[] = {
                {INT_SZ, &num_points},
                {PTR_SZ, oskar_mem_buffer_const(l)},
                {PTR_SZ, oskar_mem_buffer_const(m)},
                {is_dbl ? DBL_SZ : FLT_SZ, is_dbl ?
                        (const void*)&inv_2_var : (const void*)&inv_2_var_f},
                {PTR_SZ, oskar_mem_buffer(out)}
        };
        oskar_device_launch_kernel(k, location, 1, local_size, global_size,
                sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status);
    }
}
/* Wrapper. */
void oskar_convert_ecef_to_station_uvw(int num_stations, const oskar_Mem* x,
        const oskar_Mem* y, const oskar_Mem* z, double ra0_rad,
        double dec0_rad, double gast, oskar_Mem* u, oskar_Mem* v,
        oskar_Mem* w, int* status)
{
    int type, location;
    double ha0_rad;

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

    /* Get data type and location of the input coordinates. */
    type = oskar_mem_type(x);
    location = oskar_mem_location(x);

    /* Check that the memory is allocated. */
    if (!oskar_mem_allocated(u) || !oskar_mem_allocated(v) ||
            !oskar_mem_allocated(w) || !oskar_mem_allocated(x) ||
            !oskar_mem_allocated(y) || !oskar_mem_allocated(z))
    {
        *status = OSKAR_ERR_MEMORY_NOT_ALLOCATED;
        return;
    }

    /* Check that the data dimensions are OK. */
    if ((int)oskar_mem_length(u) < num_stations ||
            (int)oskar_mem_length(v) < num_stations ||
            (int)oskar_mem_length(w) < num_stations ||
            (int)oskar_mem_length(x) < num_stations ||
            (int)oskar_mem_length(y) < num_stations ||
            (int)oskar_mem_length(z) < num_stations)
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }

    /* Check that the data are in the right location. */
    if (oskar_mem_location(y) != location ||
            oskar_mem_location(z) != location ||
            oskar_mem_location(u) != location ||
            oskar_mem_location(v) != location ||
            oskar_mem_location(w) != location)
    {
        *status = OSKAR_ERR_BAD_LOCATION;
        return;
    }

    /* Check that the data is of the right type. */
    if (oskar_mem_type(y) != type || oskar_mem_type(z) != type ||
            oskar_mem_type(u) != type || oskar_mem_type(v) != type ||
            oskar_mem_type(w) != type)
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }

    /* Evaluate Greenwich Hour Angle of phase centre. */
    ha0_rad = gast - ra0_rad;

    /* Evaluate station u,v,w coordinates. */
    if (location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        if (type == OSKAR_SINGLE)
        {
            oskar_convert_ecef_to_station_uvw_cuda_f(num_stations,
                    oskar_mem_float_const(x, status),
                    oskar_mem_float_const(y, status),
                    oskar_mem_float_const(z, status),
                    (float)ha0_rad, (float)dec0_rad,
                    oskar_mem_float(u, status),
                    oskar_mem_float(v, status),
                    oskar_mem_float(w, status));
        }
        else if (type == OSKAR_DOUBLE)
        {
            oskar_convert_ecef_to_station_uvw_cuda_d(num_stations,
                    oskar_mem_double_const(x, status),
                    oskar_mem_double_const(y, status),
                    oskar_mem_double_const(z, status),
                    ha0_rad, dec0_rad,
                    oskar_mem_double(u, status),
                    oskar_mem_double(v, status),
                    oskar_mem_double(w, status));
        }
        else
        {
            *status = OSKAR_ERR_BAD_DATA_TYPE;
        }
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else if (location == OSKAR_CPU)
    {
        if (type == OSKAR_SINGLE)
        {
            oskar_convert_ecef_to_station_uvw_f(num_stations,
                    oskar_mem_float_const(x, status),
                    oskar_mem_float_const(y, status),
                    oskar_mem_float_const(z, status),
                    (float)ha0_rad, (float)dec0_rad,
                    oskar_mem_float(u, status),
                    oskar_mem_float(v, status),
                    oskar_mem_float(w, status));
        }
        else if (type == OSKAR_DOUBLE)
        {
            oskar_convert_ecef_to_station_uvw_d(num_stations,
                    oskar_mem_double_const(x, status),
                    oskar_mem_double_const(y, status),
                    oskar_mem_double_const(z, status),
                    ha0_rad, dec0_rad,
                    oskar_mem_double(u, status),
                    oskar_mem_double(v, status),
                    oskar_mem_double(w, status));
        }
        else
        {
            *status = OSKAR_ERR_BAD_DATA_TYPE;
        }
    }
    else
    {
        *status = OSKAR_ERR_BAD_LOCATION;
    }
}
예제 #19
0
/* Wrapper. */
void oskar_convert_enu_directions_to_theta_phi(int num_points,
        const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z,
        double delta_phi, oskar_Mem* theta, oskar_Mem* phi, int* status)
{
    int type, location;

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

    /* Get data type and location. */
    type = oskar_mem_type(theta);
    location = oskar_mem_location(theta);

    /* Compute modified theta and phi coordinates. */
    if (location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        if (type == OSKAR_SINGLE)
        {
            oskar_convert_enu_directions_to_theta_phi_cuda_f(num_points,
                    oskar_mem_float_const(x, status),
                    oskar_mem_float_const(y, status),
                    oskar_mem_float_const(z, status), (float)delta_phi,
                    oskar_mem_float(theta, status),
                    oskar_mem_float(phi, status));
            oskar_device_check_error(status);
        }
        else if (type == OSKAR_DOUBLE)
        {
            oskar_convert_enu_directions_to_theta_phi_cuda_d(num_points,
                    oskar_mem_double_const(x, status),
                    oskar_mem_double_const(y, status),
                    oskar_mem_double_const(z, status), delta_phi,
                    oskar_mem_double(theta, status),
                    oskar_mem_double(phi, status));
            oskar_device_check_error(status);
        }
        else
            *status = OSKAR_ERR_BAD_DATA_TYPE;
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else if (location == OSKAR_CPU)
    {
        if (type == OSKAR_SINGLE)
        {
            oskar_convert_enu_directions_to_theta_phi_f(num_points,
                    oskar_mem_float_const(x, status),
                    oskar_mem_float_const(y, status),
                    oskar_mem_float_const(z, status), (float)delta_phi,
                    oskar_mem_float(theta, status),
                    oskar_mem_float(phi, status));
        }
        else if (type == OSKAR_DOUBLE)
        {
            oskar_convert_enu_directions_to_theta_phi_d(num_points,
                    oskar_mem_double_const(x, status),
                    oskar_mem_double_const(y, status),
                    oskar_mem_double_const(z, status), delta_phi,
                    oskar_mem_double(theta, status),
                    oskar_mem_double(phi, status));
        }
        else
            *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
}
void oskar_sky_append_to_set(int* set_size, oskar_Sky*** set_ptr,
        int max_sources_per_model, const oskar_Sky* model, int* status)
{
    int free_space, space_required, num_extra_models, number_to_copy;
    int i, j, type, location, from_offset;
    oskar_Sky **set;
    size_t new_size;

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

    /* Get type and location. */
    type     = oskar_sky_precision(model);
    location = oskar_sky_mem_location(model);
    if (location != OSKAR_CPU)
    {
        *status = OSKAR_ERR_BAD_LOCATION;
        return;
    }

    /* Work out if the set needs to be resized, and if so by how much. */
    free_space = (*set_size == 0) ? 0 :
            max_sources_per_model - (*set_ptr)[*set_size - 1]->num_sources;
    space_required = model->num_sources - free_space;
    num_extra_models = (space_required + max_sources_per_model - 1)
            / max_sources_per_model;

    /* Sanity check. */
    if (num_extra_models < 0)
    {
        *status = OSKAR_ERR_INVALID_ARGUMENT;
        return;
    }

    /* Resize the array of sky model handles. */
    new_size = (*set_size + num_extra_models) * sizeof(oskar_Sky*);
    *set_ptr = realloc((*set_ptr), new_size);
    set = *set_ptr;
    for (i = *set_size; i < *set_size + num_extra_models; ++i)
    {
        set[i] = oskar_sky_create(type, location,
                max_sources_per_model, status);
        /* TODO Please clarify this statement and explain why it's needed. */
        /* Set the number sources to zero as this is the number currently
         * allocated in the model. */
        set[i]->num_sources = 0;
    }

    if (*status) return;

    /* Copy sources from the model into the set. */
    /* Loop over set entries with free space and copy sources into them. */
    number_to_copy = model->num_sources;
    from_offset = 0;
    for (i = (*set_size-1 > 0) ? *set_size-1 : 0;
            i < *set_size + num_extra_models; ++i)
    {
        int n_copy, offset_dst;
        offset_dst = oskar_sky_num_sources(set[i]);
        free_space = max_sources_per_model - offset_dst;
        n_copy = MIN(free_space, number_to_copy);
        oskar_sky_copy_contents(set[i], model, offset_dst, from_offset,
                n_copy, status);
        if (*status) break;
        set[i]->num_sources = n_copy + offset_dst;
        number_to_copy     -= n_copy;
        from_offset        += n_copy;
    }

    if (*status) return;

    /* Set the use extended flag if needed. */
    for (j = (*set_size-1 > 0) ? *set_size-1 : 0;
            j < *set_size + num_extra_models; ++j)
    {
        oskar_Sky* sky = set[j];
        const oskar_Mem *major, *minor;

        /* If any source in the model is extended, set the flag. */
        major = oskar_sky_fwhm_major_rad_const(sky);
        minor = oskar_sky_fwhm_minor_rad_const(sky);
        if (type == OSKAR_DOUBLE)
        {
            const double *maj_, *min_;
            maj_ = oskar_mem_double_const(major, status);
            min_ = oskar_mem_double_const(minor, status);
            for (i = 0; i < sky->num_sources; ++i)
            {
                if (maj_[i] > 0.0 || min_[i] > 0.0)
                {
                    sky->use_extended = OSKAR_TRUE;
                    break;
                }
            }
        }
        else
        {
            const float *maj_, *min_;
            maj_ = oskar_mem_float_const(major, status);
            min_ = oskar_mem_float_const(minor, status);
            for (i = 0; i < sky->num_sources; ++i)
            {
                if (maj_[i] > 0.0 || min_[i] > 0.0)
                {
                    sky->use_extended = OSKAR_TRUE;
                    break;
                }
            }
        }
    }

    /* Update the set size */
    *set_size += num_extra_models;
}
void oskar_mem_evaluate_relative_error(const oskar_Mem* val_approx,
        const oskar_Mem* val_accurate, double* min_rel_error,
        double* max_rel_error, double* avg_rel_error, double* std_rel_error,
        int* status)
{
    int prec_approx, prec_accurate;
    size_t i, n;
    const oskar_Mem *app_ptr, *acc_ptr;
    oskar_Mem *approx_temp = 0, *accurate_temp = 0;
    double old_m = 0.0, new_m = 0.0, old_s = 0.0, new_s = 0.0;

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

    /* Initialise outputs. */
    if (max_rel_error) *max_rel_error = -DBL_MAX;
    if (min_rel_error) *min_rel_error = DBL_MAX;
    if (avg_rel_error) *avg_rel_error = DBL_MAX;
    if (std_rel_error) *std_rel_error = DBL_MAX;

    /* Type and dimension check. */
    if (oskar_mem_is_matrix(val_approx) && !oskar_mem_is_matrix(val_accurate))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (oskar_mem_is_complex(val_approx) && !oskar_mem_is_complex(val_accurate))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }

    /* Get and check base types. */
    prec_approx = oskar_mem_precision(val_approx);
    prec_accurate = oskar_mem_precision(val_accurate);
    if (prec_approx != OSKAR_SINGLE && prec_approx != OSKAR_DOUBLE)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    if (prec_accurate != OSKAR_SINGLE && prec_accurate != OSKAR_DOUBLE)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }

    /* Get number of elements to check. */
    n = oskar_mem_length(val_approx) < oskar_mem_length(val_accurate) ?
            oskar_mem_length(val_approx) : oskar_mem_length(val_accurate);
    if (oskar_mem_is_matrix(val_approx)) n *= 4;

    /* Copy input data to temporary CPU arrays if required. */
    app_ptr = val_approx;
    acc_ptr = val_accurate;
    if (oskar_mem_location(val_approx) != OSKAR_CPU)
    {
        approx_temp = oskar_mem_create_copy(val_approx, OSKAR_CPU,
                status);
        if (*status)
        {
            oskar_mem_free(approx_temp, status);
            return;
        }
        app_ptr = approx_temp;
    }
    if (oskar_mem_location(val_accurate) != OSKAR_CPU)
    {
        accurate_temp = oskar_mem_create_copy(val_accurate, OSKAR_CPU,
                status);
        if (*status)
        {
            oskar_mem_free(accurate_temp, status);
            return;
        }
        acc_ptr = accurate_temp;
    }

    /* Check numbers are the same, to appropriate precision. */
    if (prec_approx == OSKAR_SINGLE && prec_accurate == OSKAR_SINGLE)
    {
        const float *approx, *accurate;
        approx = oskar_mem_float_const(app_ptr, status);
        accurate = oskar_mem_float_const(acc_ptr, status);
        CHECK_ELEMENTS(1e-5)
    }
    else if (prec_approx == OSKAR_DOUBLE && prec_accurate == OSKAR_SINGLE)
예제 #22
0
/* Wrapper. */
void oskar_evaluate_jones_K(oskar_Jones* K, int num_sources,
        const oskar_Mem* l, const oskar_Mem* m, const oskar_Mem* n,
        const oskar_Mem* u, const oskar_Mem* v, const oskar_Mem* w,
        double frequency_hz, const oskar_Mem* source_filter,
        double source_filter_min, double source_filter_max, int* status)
{
    int num_stations, jones_type, base_type, location;
    double wavenumber;

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

    /* Get the Jones matrix block meta-data. */
    jones_type = oskar_jones_type(K);
    base_type = oskar_type_precision(jones_type);
    location = oskar_jones_mem_location(K);
    num_stations = oskar_jones_num_stations(K);
    wavenumber = 2.0 * M_PI * frequency_hz / 299792458.0;

    /* Check that the data is in the right location. */
    if (oskar_mem_location(l) != location ||
            oskar_mem_location(m) != location ||
            oskar_mem_location(n) != location ||
            oskar_mem_location(source_filter) != location ||
            oskar_mem_location(u) != location ||
            oskar_mem_location(v) != location ||
            oskar_mem_location(w) != location)
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }

    /* Check that the data are of the right type. */
    if (!oskar_type_is_complex(jones_type) ||
            oskar_type_is_matrix(jones_type))
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    if (base_type != oskar_mem_type(l) || base_type != oskar_mem_type(m) ||
            base_type != oskar_mem_type(n) || base_type != oskar_mem_type(u) ||
            base_type != oskar_mem_type(v) || base_type != oskar_mem_type(w) ||
            base_type != oskar_mem_type(source_filter))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }

    /* Evaluate Jones matrices. */
    if (location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        if (jones_type == OSKAR_SINGLE_COMPLEX)
        {
            oskar_evaluate_jones_K_cuda_f(oskar_jones_float2(K, status),
                    num_sources,
                    oskar_mem_float_const(l, status),
                    oskar_mem_float_const(m, status),
                    oskar_mem_float_const(n, status),
                    num_stations,
                    oskar_mem_float_const(u, status),
                    oskar_mem_float_const(v, status),
                    oskar_mem_float_const(w, status), wavenumber,
                    oskar_mem_float_const(source_filter, status),
                    source_filter_min, source_filter_max);
        }
        else if (jones_type == OSKAR_DOUBLE_COMPLEX)
        {
            oskar_evaluate_jones_K_cuda_d(oskar_jones_double2(K, status),
                    num_sources,
                    oskar_mem_double_const(l, status),
                    oskar_mem_double_const(m, status),
                    oskar_mem_double_const(n, status),
                    num_stations,
                    oskar_mem_double_const(u, status),
                    oskar_mem_double_const(v, status),
                    oskar_mem_double_const(w, status), wavenumber,
                    oskar_mem_double_const(source_filter, status),
                    source_filter_min, source_filter_max);
        }
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else if (location == OSKAR_CPU)
    {
        if (jones_type == OSKAR_SINGLE_COMPLEX)
        {
            oskar_evaluate_jones_K_f(oskar_jones_float2(K, status),
                    num_sources,
                    oskar_mem_float_const(l, status),
                    oskar_mem_float_const(m, status),
                    oskar_mem_float_const(n, status),
                    num_stations,
                    oskar_mem_float_const(u, status),
                    oskar_mem_float_const(v, status),
                    oskar_mem_float_const(w, status), wavenumber,
                    oskar_mem_float_const(source_filter, status),
                    source_filter_min, source_filter_max);

        }
        else if (jones_type == OSKAR_DOUBLE_COMPLEX)
        {
            oskar_evaluate_jones_K_d(oskar_jones_double2(K, status),
                    num_sources,
                    oskar_mem_double_const(l, status),
                    oskar_mem_double_const(m, status),
                    oskar_mem_double_const(n, status),
                    num_stations,
                    oskar_mem_double_const(u, status),
                    oskar_mem_double_const(v, status),
                    oskar_mem_double_const(w, status), wavenumber,
                    oskar_mem_double_const(source_filter, status),
                    source_filter_min, source_filter_max);
        }
    }
}
void oskar_imager_update_plane_wproj(oskar_Imager* h, size_t num_vis,
        const oskar_Mem* uu, const oskar_Mem* vv, const oskar_Mem* ww,
        const oskar_Mem* amps, const oskar_Mem* weight, oskar_Mem* plane,
        double* plane_norm, size_t* num_skipped, int* status)
{
    int grid_size;
    size_t num_cells;
    if (*status) return;
    grid_size = oskar_imager_plane_size(h);
    num_cells = grid_size * grid_size;
    if (oskar_mem_precision(plane) != h->imager_prec)
        *status = OSKAR_ERR_TYPE_MISMATCH;
    if (oskar_mem_length(plane) < num_cells)
        oskar_mem_realloc(plane, num_cells, status);
    if (*status) return;
    if (h->imager_prec == OSKAR_DOUBLE)
        oskar_grid_wproj_d(h->num_w_planes,
                oskar_mem_int_const(h->w_support, status),
                h->oversample, h->conv_size_half,
                oskar_mem_double_const(h->w_kernels, status), num_vis,
                oskar_mem_double_const(uu, status),
                oskar_mem_double_const(vv, status),
                oskar_mem_double_const(ww, status),
                oskar_mem_double_const(amps, status),
                oskar_mem_double_const(weight, status),
                h->cellsize_rad, h->w_scale,
                grid_size, num_skipped, plane_norm,
                oskar_mem_double(plane, status));
    else
    {
        char *fname = 0;
#if SAVE_INPUT_DAT || SAVE_OUTPUT_DAT || SAVE_GRID
        fname = (char*) calloc(20 +
                h->input_root ? strlen(h->input_root) : 0, 1);
#endif
#if SAVE_INPUT_DAT
        {
            const float cellsize_rad_tmp = (const float) (h->cellsize_rad);
            const float w_scale_tmp = (const float) (h->w_scale);
            const size_t num_w_planes = (size_t) (h->num_w_planes);
            FILE* f;
            sprintf(fname, "%s_INPUT.dat", h->input_root);
            f = fopen(fname, "wb");
            fwrite(&num_w_planes, sizeof(size_t), 1, f);
            fwrite(oskar_mem_void_const(h->w_support),
                    sizeof(int), num_w_planes, f);
            fwrite(&h->oversample, sizeof(int), 1, f);
            fwrite(&h->conv_size_half, sizeof(int), 1, f);
            fwrite(oskar_mem_void_const(h->w_kernels), 2 * sizeof(float),
                    h->num_w_planes * h->conv_size_half * h->conv_size_half, f);
            fwrite(&num_vis, sizeof(size_t), 1, f);
            fwrite(oskar_mem_void_const(uu), sizeof(float), num_vis, f);
            fwrite(oskar_mem_void_const(vv), sizeof(float), num_vis, f);
            fwrite(oskar_mem_void_const(ww), sizeof(float), num_vis, f);
            fwrite(oskar_mem_void_const(amps), 2 * sizeof(float), num_vis, f);
            fwrite(oskar_mem_void_const(weight), sizeof(float), num_vis, f);
            fwrite(&cellsize_rad_tmp, sizeof(float), 1, f);
            fwrite(&w_scale_tmp, sizeof(float), 1, f);
            fwrite(&grid_size, sizeof(int), 1, f);
            fclose(f);
        }
#endif
        oskar_grid_wproj_f(h->num_w_planes,
                oskar_mem_int_const(h->w_support, status),
                h->oversample, h->conv_size_half,
                oskar_mem_float_const(h->w_kernels, status), num_vis,
                oskar_mem_float_const(uu, status),
                oskar_mem_float_const(vv, status),
                oskar_mem_float_const(ww, status),
                oskar_mem_float_const(amps, status),
                oskar_mem_float_const(weight, status),
                (float) (h->cellsize_rad), (float) (h->w_scale),
                grid_size, num_skipped, plane_norm,
                oskar_mem_float(plane, status));
#if SAVE_OUTPUT_DAT
        {
            FILE* f;
            sprintf(fname, "%s_OUTPUT.dat", h->input_root);
            f = fopen(fname, "wb");
            fwrite(num_skipped, sizeof(size_t), 1, f);
            fwrite(plane_norm, sizeof(double), 1, f);
            fwrite(&grid_size, sizeof(int), 1, f);
            fwrite(oskar_mem_void_const(plane), 2 * sizeof(float), num_cells, f);
            fclose(f);
        }
#endif
#if SAVE_GRID
        sprintf(fname, "%s_GRID", h->input_root);
        oskar_mem_write_fits_cube(plane, fname,
                grid_size, grid_size, 1, 0, status);
#endif
        free(fname);
    }
}
예제 #24
0
void oskar_splines_evaluate(const oskar_Splines* spline,
        int num_points, const oskar_Mem* x, const oskar_Mem* y,
        int stride_out, int offset_out, oskar_Mem* output, int* status)
{
    if (*status) return;
    const int type = oskar_splines_precision(spline);
    const int location = oskar_splines_mem_location(spline);
    const int nx = oskar_splines_num_knots_x_theta(spline);
    const int ny = oskar_splines_num_knots_y_phi(spline);
    const oskar_Mem* tx = oskar_splines_knots_x_theta_const(spline);
    const oskar_Mem* ty = oskar_splines_knots_y_phi_const(spline);
    const oskar_Mem* coeff = oskar_splines_coeff_const(spline);
    if (type != oskar_mem_type(x) || type != oskar_mem_type(y))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (location != oskar_mem_location(output) ||
            location != oskar_mem_location(x) ||
            location != oskar_mem_location(y))
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }
    if (location == OSKAR_CPU)
    {
        int i;
        if (type == OSKAR_SINGLE)
        {
            const float *tx_, *ty_, *coeff_, *x_, *y_;
            float *out;
            tx_    = oskar_mem_float_const(tx, status);
            ty_    = oskar_mem_float_const(ty, status);
            coeff_ = oskar_mem_float_const(coeff, status);
            x_     = oskar_mem_float_const(x, status);
            y_     = oskar_mem_float_const(y, status);
            out    = oskar_mem_float(output, status) + offset_out;
            if (nx == 0 || ny == 0 || !tx_ || !ty_ || !coeff_)
                for (i = 0; i < num_points; ++i) out[i * stride_out] = 0.0f;
            else
            {
                float x1, y1, wrk[8];
                int iwrk1[2], kwrk1 = 2, lwrk = 8, err = 0;
                for (i = 0; i < num_points; ++i)
                {
                    x1 = x_[i];
                    y1 = y_[i];
                    oskar_dierckx_bispev_f(tx_, nx, ty_, ny, coeff_, 3, 3,
                            &x1, 1, &y1, 1, &out[i * stride_out],
                            wrk, lwrk, iwrk1, kwrk1, &err);
                    if (err != 0)
                    {
                        *status = OSKAR_ERR_SPLINE_EVAL_FAIL;
                        return;
                    }
                }
            }
        }
        else if (type == OSKAR_DOUBLE)
        {
            const double *tx_, *ty_, *coeff_, *x_, *y_;
            double *out;
            tx_    = oskar_mem_double_const(tx, status);
            ty_    = oskar_mem_double_const(ty, status);
            coeff_ = oskar_mem_double_const(coeff, status);
            x_     = oskar_mem_double_const(x, status);
            y_     = oskar_mem_double_const(y, status);
            out    = oskar_mem_double(output, status) + offset_out;
            if (nx == 0 || ny == 0 || !tx_ || !ty_ || !coeff_)
                for (i = 0; i < num_points; ++i) out[i * stride_out] = 0.0;
            else
            {
                double x1, y1, wrk[8];
                int iwrk1[2], kwrk1 = 2, lwrk = 8, err = 0;
                for (i = 0; i < num_points; ++i)
                {
                    x1 = x_[i];
                    y1 = y_[i];
                    oskar_dierckx_bispev_d(tx_, nx, ty_, ny, coeff_, 3, 3,
                            &x1, 1, &y1, 1, &out[i * stride_out],
                            wrk, lwrk, iwrk1, kwrk1, &err);
                    if (err != 0)
                    {
                        *status = OSKAR_ERR_SPLINE_EVAL_FAIL;
                        return;
                    }
                }
            }
        }
        else
            *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
    else
    {
        size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1};
        const char* k = 0;
        if (nx == 0 || ny == 0)
        {
            if (type == OSKAR_DOUBLE)      k = "set_zeros_stride_double";
            else if (type == OSKAR_SINGLE) k = "set_zeros_stride_float";
            else
            {
                *status = OSKAR_ERR_BAD_DATA_TYPE;
                return;
            }
            oskar_device_check_local_size(location, 0, local_size);
            global_size[0] = oskar_device_global_size(
                    (size_t) num_points, local_size[0]);
            const oskar_Arg args[] = {
                    {INT_SZ, &num_points},
                    {INT_SZ, &stride_out},
                    {INT_SZ, &offset_out},
                    {PTR_SZ, oskar_mem_buffer(output)}
            };
            oskar_device_launch_kernel(k, location, 1, local_size, global_size,
                    sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status);
        }
        else
        {
            if (type == OSKAR_DOUBLE)      k = "dierckx_bispev_bicubic_double";
            else if (type == OSKAR_SINGLE) k = "dierckx_bispev_bicubic_float";
            else
            {
                *status = OSKAR_ERR_BAD_DATA_TYPE;
                return;
            }
            oskar_device_check_local_size(location, 0, local_size);
            global_size[0] = oskar_device_global_size(
                    (size_t) num_points, local_size[0]);
            const oskar_Arg args[] = {
                    {PTR_SZ, oskar_mem_buffer_const(tx)},
                    {INT_SZ, &nx},
                    {PTR_SZ, oskar_mem_buffer_const(ty)},
                    {INT_SZ, &ny},
                    {PTR_SZ, oskar_mem_buffer_const(coeff)},
                    {INT_SZ, &num_points},
                    {PTR_SZ, oskar_mem_buffer_const(x)},
                    {PTR_SZ, oskar_mem_buffer_const(y)},
                    {INT_SZ, &stride_out},
                    {INT_SZ, &offset_out},
                    {PTR_SZ, oskar_mem_buffer(output)}
            };
            oskar_device_launch_kernel(k, location, 1, local_size, global_size,
                    sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status);
        }
    }
}
void oskar_evaluate_vla_beam_pbcor(oskar_Mem* beam, int num_sources,
        const oskar_Mem* l, const oskar_Mem* m, double frequency_hz,
        int* status)
{
    int index, precision, type, location;
    double f, p1, p2, p3;

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

    /* Check type and location. */
    precision = oskar_mem_precision(beam);
    type = oskar_mem_type(beam);
    location = oskar_mem_location(beam);
    if (precision != oskar_mem_type(l) || precision != oskar_mem_type(m))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (location != oskar_mem_location(l) || location != oskar_mem_location(m))
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }

    /* Find the nearest frequency at which data exists. */
    index = oskar_find_closest_match_d(frequency_hz / 1.0e9,
            sizeof(freqs_ghz) / sizeof(double), freqs_ghz);
    f = frequency_hz / 1.0e9;
    p1 = p1s[index];
    p2 = p2s[index];
    p3 = p3s[index];

    /* Switch on precision. */
    if (precision == OSKAR_SINGLE)
    {
        const float *l_, *m_;
        l_ = oskar_mem_float_const(l, status);
        m_ = oskar_mem_float_const(m, status);

        if (location == OSKAR_GPU)
        {
#ifdef OSKAR_HAVE_CUDA
            if (type == OSKAR_SINGLE)
            {
                oskar_evaluate_vla_beam_pbcor_cuda_f(
                        oskar_mem_float(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            else if (type == OSKAR_SINGLE_COMPLEX)
            {
                oskar_evaluate_vla_beam_pbcor_complex_cuda_f(
                        oskar_mem_float2(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            else if (type == OSKAR_SINGLE_COMPLEX_MATRIX)
            {
                oskar_evaluate_vla_beam_pbcor_matrix_cuda_f(
                        oskar_mem_float4c(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
        else if (location == OSKAR_CPU)
        {
            if (type == OSKAR_SINGLE)
            {
                oskar_evaluate_vla_beam_pbcor_f(
                        oskar_mem_float(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            else if (type == OSKAR_SINGLE_COMPLEX)
            {
                oskar_evaluate_vla_beam_pbcor_complex_f(
                        oskar_mem_float2(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            else if (type == OSKAR_SINGLE_COMPLEX_MATRIX)
            {
                oskar_evaluate_vla_beam_pbcor_matrix_f(
                        oskar_mem_float4c(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
        }
    }
    else if (precision == OSKAR_DOUBLE)
    {
        const double *l_, *m_;
        l_ = oskar_mem_double_const(l, status);
        m_ = oskar_mem_double_const(m, status);

        if (location == OSKAR_GPU)
        {
#ifdef OSKAR_HAVE_CUDA
            if (type == OSKAR_DOUBLE)
            {
                oskar_evaluate_vla_beam_pbcor_cuda_d(
                        oskar_mem_double(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            else if (type == OSKAR_DOUBLE_COMPLEX)
            {
                oskar_evaluate_vla_beam_pbcor_complex_cuda_d(
                        oskar_mem_double2(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            else if (type == OSKAR_DOUBLE_COMPLEX_MATRIX)
            {
                oskar_evaluate_vla_beam_pbcor_matrix_cuda_d(
                        oskar_mem_double4c(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
        else if (location == OSKAR_CPU)
        {
            if (type == OSKAR_DOUBLE)
            {
                oskar_evaluate_vla_beam_pbcor_d(
                        oskar_mem_double(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            else if (type == OSKAR_DOUBLE_COMPLEX)
            {
                oskar_evaluate_vla_beam_pbcor_complex_d(
                        oskar_mem_double2(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
            else if (type == OSKAR_DOUBLE_COMPLEX_MATRIX)
            {
                oskar_evaluate_vla_beam_pbcor_matrix_d(
                        oskar_mem_double4c(beam, status),
                        num_sources, l_, m_, f, p1, p2, p3);
            }
        }
    }
    else
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
}
void oskar_evaluate_tec_tid(oskar_Mem* tec, int num_directions,
        const oskar_Mem* lon, const oskar_Mem* lat,
        const oskar_Mem* rel_path_length, double TEC0,
        oskar_SettingsTIDscreen* TID, double gast)
{
    int i, j, type;
    double pp_lon, pp_lat;
    double pp_sec;
    double pp_tec;
    double amp, w, th, v; /* TID parameters */
    double time;
    double earth_radius = 6365.0; /* km -- FIXME */
    int status = 0;

    /* TODO check types, dimensions etc of memory */
    type = oskar_mem_type(tec);

    oskar_mem_set_value_real(tec, 0.0, 0, 0, &status);

    /* Loop over TIDs */
    for (i = 0; i < TID->num_components; ++i)
    {
        amp = TID->amp[i];
        /* convert from km to rads */
        w = TID->wavelength[i] / (earth_radius + TID->height_km);
        th = TID->theta[i] * M_PI/180.;
        /* convert from km/h to rad/s */
        v = (TID->speed[i]/(earth_radius + TID->height_km)) / 3600;

        time = gast * 86400.0; /* days->sec */

        /* Loop over directions */
        for (j = 0; j < num_directions; ++j)
        {
            if (type == OSKAR_DOUBLE)
            {
                pp_lon = oskar_mem_double_const(lon, &status)[j];
                pp_lat = oskar_mem_double_const(lat, &status)[j];
                pp_sec = oskar_mem_double_const(rel_path_length, &status)[j];
                pp_tec = pp_sec * amp * TEC0 * (
                        cos( (2.0*M_PI/w) * (cos(th)*pp_lon - v*time) ) +
                        cos( (2.0*M_PI/w) * (sin(th)*pp_lat - v*time) )
                        );
                pp_tec += TEC0;
                oskar_mem_double(tec, &status)[j] += pp_tec;
            }
            else
            {
                pp_lon = (double)oskar_mem_float_const(lon, &status)[j];
                pp_lat = (double)oskar_mem_float_const(lat, &status)[j];
                pp_sec = (double)oskar_mem_float_const(rel_path_length, &status)[j];
                pp_tec = pp_sec * amp * TEC0 * (
                        cos( (2.0*M_PI/w) * (cos(th)*pp_lon - v*time) ) +
                        cos( (2.0*M_PI/w) * (sin(th)*pp_lat - v*time) )
                );
                pp_tec += TEC0;
                oskar_mem_float(tec, &status)[j] += (float)pp_tec;
            }
        } /* loop over directions */
    } /* loop over components. */
}
void oskar_sky_evaluate_gaussian_source_parameters(oskar_Sky* sky,
        int zero_failed_sources, double ra0, double dec0, int* num_failed,
        int* status)
{
    int i, j, num_sources;
    int type;

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

    /* Return if memory is not on the CPU. */
    if (oskar_sky_mem_location(sky) != OSKAR_CPU)
    {
        *status = OSKAR_ERR_BAD_LOCATION;
        return;
    }

    /* Get data type and number of sources. */
    type = oskar_sky_precision(sky);
    num_sources = oskar_sky_num_sources(sky);

    /* Switch on type. */
    if (type == OSKAR_DOUBLE)
    {
        /* Double precision. */
        const double *ra_, *dec_, *maj_, *min_, *pa_;
        double *I_, *Q_, *U_, *V_, *a_, *b_, *c_;
        double cos_pa_2, sin_pa_2, sin_2pa, inv_std_min_2, inv_std_maj_2;
        double ellipse_a, ellipse_b, maj, min, pa, cos_pa, sin_pa, t;
        double l[ELLIPSE_PTS], m[ELLIPSE_PTS];
        double work1[5 * ELLIPSE_PTS], work2[5 * ELLIPSE_PTS];
        double lon[ELLIPSE_PTS], lat[ELLIPSE_PTS];
        double x[ELLIPSE_PTS], y[ELLIPSE_PTS], z[ELLIPSE_PTS];
        ra_  = oskar_mem_double_const(oskar_sky_ra_rad_const(sky), status);
        dec_ = oskar_mem_double_const(oskar_sky_dec_rad_const(sky), status);
        maj_ = oskar_mem_double_const(oskar_sky_fwhm_major_rad_const(sky), status);
        min_ = oskar_mem_double_const(oskar_sky_fwhm_minor_rad_const(sky), status);
        pa_  = oskar_mem_double_const(oskar_sky_position_angle_rad_const(sky), status);
        I_   = oskar_mem_double(oskar_sky_I(sky), status);
        Q_   = oskar_mem_double(oskar_sky_Q(sky), status);
        U_   = oskar_mem_double(oskar_sky_U(sky), status);
        V_   = oskar_mem_double(oskar_sky_V(sky), status);
        a_   = oskar_mem_double(oskar_sky_gaussian_a(sky), status);
        b_   = oskar_mem_double(oskar_sky_gaussian_b(sky), status);
        c_   = oskar_mem_double(oskar_sky_gaussian_c(sky), status);

        for (i = 0; i < num_sources; ++i)
        {
            /* Note: could do something different from the projection below
             * in the case of a line (i.e. maj or min = 0), as in this case
             * there is no ellipse to project, only two points.
             * -- This continue could then be a if() .. else() instead.
             */
            if (maj_[i] == 0.0 && min_[i] == 0.0) continue;

            /* Evaluate shape of ellipse on the l,m plane. */
            ellipse_a = maj_[i]/2.0;
            ellipse_b = min_[i]/2.0;
            cos_pa = cos(pa_[i]);
            sin_pa = sin(pa_[i]);
            for (j = 0; j < ELLIPSE_PTS; ++j)
            {
                t = j * 60.0 * M_PI / 180.0;
                l[j] = ellipse_a*cos(t)*sin_pa + ellipse_b*sin(t)*cos_pa;
                m[j] = ellipse_a*cos(t)*cos_pa - ellipse_b*sin(t)*sin_pa;
            }
            oskar_convert_relative_directions_to_lon_lat_2d_d(ELLIPSE_PTS,
                    l, m, 0.0, 0.0, lon, lat);

            /* Rotate on the sphere. */
            oskar_convert_lon_lat_to_xyz_d(ELLIPSE_PTS, lon, lat, x, y, z);
            oskar_rotate_sph_d(ELLIPSE_PTS, x, y, z, ra_[i], dec_[i]);
            oskar_convert_xyz_to_lon_lat_d(ELLIPSE_PTS, x, y, z, lon, lat);

            oskar_convert_lon_lat_to_relative_directions_2d_d(
                    ELLIPSE_PTS, lon, lat, ra0, dec0, l, m);

            /* Get new major and minor axes and position angle. */
            oskar_fit_ellipse_d(&maj, &min, &pa, ELLIPSE_PTS, l, m, work1,
                    work2, status);

            /* Check if fitting failed. */
            if (*status == OSKAR_ERR_ELLIPSE_FIT_FAILED)
            {
                if (zero_failed_sources)
                {
                    I_[i] = 0.0;
                    Q_[i] = 0.0;
                    U_[i] = 0.0;
                    V_[i] = 0.0;
                }
                ++(*num_failed);
                *status = 0;
                continue;
            }
            else if (*status) break;

            /* Evaluate ellipse parameters. */
            inv_std_maj_2 = 0.5 * (maj * maj) * M_PI_2_2_LN_2;
            inv_std_min_2 = 0.5 * (min * min) * M_PI_2_2_LN_2;
            cos_pa_2 = cos(pa) * cos(pa);
            sin_pa_2 = sin(pa) * sin(pa);
            sin_2pa  = sin(2.0 * pa);
            a_[i] = cos_pa_2*inv_std_min_2     + sin_pa_2*inv_std_maj_2;
            b_[i] = -sin_2pa*inv_std_min_2*0.5 + sin_2pa *inv_std_maj_2*0.5;
            c_[i] = sin_pa_2*inv_std_min_2     + cos_pa_2*inv_std_maj_2;
        }
    }
    else
    {
        /* Single precision. */
        const float *ra_, *dec_, *maj_, *min_, *pa_;
        float *I_, *Q_, *U_, *V_, *a_, *b_, *c_;
        float cos_pa_2, sin_pa_2, sin_2pa, inv_std_min_2, inv_std_maj_2;
        float ellipse_a, ellipse_b, maj, min, pa, cos_pa, sin_pa, t;
        float l[ELLIPSE_PTS], m[ELLIPSE_PTS];
        float work1[5 * ELLIPSE_PTS], work2[5 * ELLIPSE_PTS];
        float lon[ELLIPSE_PTS], lat[ELLIPSE_PTS];
        float x[ELLIPSE_PTS], y[ELLIPSE_PTS], z[ELLIPSE_PTS];
        ra_  = oskar_mem_float_const(oskar_sky_ra_rad_const(sky), status);
        dec_ = oskar_mem_float_const(oskar_sky_dec_rad_const(sky), status);
        maj_ = oskar_mem_float_const(oskar_sky_fwhm_major_rad_const(sky), status);
        min_ = oskar_mem_float_const(oskar_sky_fwhm_minor_rad_const(sky), status);
        pa_  = oskar_mem_float_const(oskar_sky_position_angle_rad_const(sky), status);
        I_   = oskar_mem_float(oskar_sky_I(sky), status);
        Q_   = oskar_mem_float(oskar_sky_Q(sky), status);
        U_   = oskar_mem_float(oskar_sky_U(sky), status);
        V_   = oskar_mem_float(oskar_sky_V(sky), status);
        a_   = oskar_mem_float(oskar_sky_gaussian_a(sky), status);
        b_   = oskar_mem_float(oskar_sky_gaussian_b(sky), status);
        c_   = oskar_mem_float(oskar_sky_gaussian_c(sky), status);

        for (i = 0; i < num_sources; ++i)
        {
            /* Note: could do something different from the projection below
             * in the case of a line (i.e. maj or min = 0), as in this case
             * there is no ellipse to project, only two points.
             * -- This continue could then be a if() .. else() instead.
             */
            if (maj_[i] == 0.0 && min_[i] == 0.0) continue;

            /* Evaluate shape of ellipse on the l,m plane. */
            ellipse_a = maj_[i]/2.0;
            ellipse_b = min_[i]/2.0;
            cos_pa = cos(pa_[i]);
            sin_pa = sin(pa_[i]);
            for (j = 0; j < ELLIPSE_PTS; ++j)
            {
                t = j * 60.0 * M_PI / 180.0;
                l[j] = ellipse_a*cos(t)*sin_pa + ellipse_b*sin(t)*cos_pa;
                m[j] = ellipse_a*cos(t)*cos_pa - ellipse_b*sin(t)*sin_pa;
            }
            oskar_convert_relative_directions_to_lon_lat_2d_f(ELLIPSE_PTS,
                    l, m, 0.0, 0.0, lon, lat);

            /* Rotate on the sphere. */
            oskar_convert_lon_lat_to_xyz_f(ELLIPSE_PTS, lon, lat, x, y, z);
            oskar_rotate_sph_f(ELLIPSE_PTS, x, y, z, ra_[i], dec_[i]);
            oskar_convert_xyz_to_lon_lat_f(ELLIPSE_PTS, x, y, z, lon, lat);

            oskar_convert_lon_lat_to_relative_directions_2d_f(
                    ELLIPSE_PTS, lon, lat, (float)ra0, (float)dec0, l, m);

            /* Get new major and minor axes and position angle. */
            oskar_fit_ellipse_f(&maj, &min, &pa, ELLIPSE_PTS, l, m, work1,
                    work2, status);

            /* Check if fitting failed. */
            if (*status == OSKAR_ERR_ELLIPSE_FIT_FAILED)
            {
                if (zero_failed_sources)
                {
                    I_[i] = 0.0;
                    Q_[i] = 0.0;
                    U_[i] = 0.0;
                    V_[i] = 0.0;
                }
                ++(*num_failed);
                *status = 0;
                continue;
            }
            else if (*status) break;

            /* Evaluate ellipse parameters. */
            inv_std_maj_2 = 0.5 * (maj * maj) * M_PI_2_2_LN_2;
            inv_std_min_2 = 0.5 * (min * min) * M_PI_2_2_LN_2;
            cos_pa_2 = cos(pa) * cos(pa);
            sin_pa_2 = sin(pa) * sin(pa);
            sin_2pa  = sin(2.0 * pa);
            a_[i] = cos_pa_2*inv_std_min_2     + sin_pa_2*inv_std_maj_2;
            b_[i] = -sin_2pa*inv_std_min_2*0.5 + sin_2pa *inv_std_maj_2*0.5;
            c_[i] = sin_pa_2*inv_std_min_2     + cos_pa_2*inv_std_maj_2;
        }
    }
}
void oskar_convert_ludwig3_to_theta_phi_components(
        int num_points, const oskar_Mem* phi, int stride, int offset,
        oskar_Mem* vec, int* status)
{
    if (*status) return;
    const int type = oskar_mem_type(phi);
    const int location = oskar_mem_location(phi);
    const int off_h = offset, off_v = offset + 1;
    if (!oskar_mem_is_matrix(vec))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (location == OSKAR_CPU)
    {
        if (type == OSKAR_SINGLE)
            convert_ludwig3_to_theta_phi_float(
                    num_points,
                    oskar_mem_float_const(phi, status),
                    stride, off_h, off_v,
                    oskar_mem_float2(vec, status),
                    oskar_mem_float2(vec, status));
        else if (type == OSKAR_DOUBLE)
            convert_ludwig3_to_theta_phi_double(
                    num_points,
                    oskar_mem_double_const(phi, status),
                    stride, off_h, off_v,
                    oskar_mem_double2(vec, status),
                    oskar_mem_double2(vec, status));
        else
            *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
    else
    {
        size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1};
        const char* k = 0;
        if (type == OSKAR_SINGLE)
            k = "convert_ludwig3_to_theta_phi_float";
        else if (type == OSKAR_DOUBLE)
            k = "convert_ludwig3_to_theta_phi_double";
        else
        {
            *status = OSKAR_ERR_BAD_DATA_TYPE;
            return;
        }
        oskar_device_check_local_size(location, 0, local_size);
        global_size[0] = oskar_device_global_size(
                (size_t) num_points, local_size[0]);
        const oskar_Arg args[] = {
                {INT_SZ, &num_points},
                {PTR_SZ, oskar_mem_buffer_const(phi)},
                {INT_SZ, &stride},
                {INT_SZ, &off_h},
                {INT_SZ, &off_v},
                {PTR_SZ, oskar_mem_buffer(vec)},
                {PTR_SZ, oskar_mem_buffer(vec)}
        };
        oskar_device_launch_kernel(k, location, 1, local_size, global_size,
                sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status);
    }
}
예제 #29
0
void oskar_evaluate_station_beam_gaussian(oskar_Mem* beam,
        int num_points, const oskar_Mem* l, const oskar_Mem* m,
        const oskar_Mem* horizon_mask, double fwhm_rad, int* status)
{
    int type, location;
    double fwhm_lm, std;

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

    /* Get type and check consistency. */
    type = oskar_mem_precision(beam);
    if (type != oskar_mem_type(l) || type != oskar_mem_type(m))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (type != OSKAR_SINGLE && type != OSKAR_DOUBLE)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    if (!oskar_mem_is_complex(beam))
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }

    if (fwhm_rad == 0.0)
    {
        *status = OSKAR_ERR_SETTINGS_TELESCOPE;
        return;
    }

    /* Get location and check consistency. */
    location = oskar_mem_location(beam);
    if (location != oskar_mem_location(l) ||
            location != oskar_mem_location(m))
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }

    /* Check that length of input arrays are consistent. */
    if ((int)oskar_mem_length(l) < num_points ||
            (int)oskar_mem_length(m) < num_points)
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }

    /* Resize output array if needed. */
    if ((int)oskar_mem_length(beam) < num_points)
        oskar_mem_realloc(beam, num_points, status);

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

    /* Compute Gaussian standard deviation from FWHM. */
    fwhm_lm = sin(fwhm_rad);
    std = fwhm_lm / (2.0 * sqrt(2.0 * log(2.0)));

    if (type == OSKAR_DOUBLE)
    {
        const double *l_, *m_;
        l_ = oskar_mem_double_const(l, status);
        m_ = oskar_mem_double_const(m, status);

        if (location == OSKAR_CPU)
        {
            if (oskar_mem_is_scalar(beam))
            {
                oskar_gaussian_d(oskar_mem_double2(beam, status),
                        num_points, l_, m_, std);
            }
            else
            {
                oskar_gaussian_md(oskar_mem_double4c(beam, status),
                        num_points, l_, m_, std);
            }
        }
        else
        {
#ifdef OSKAR_HAVE_CUDA
            if (oskar_mem_is_scalar(beam))
            {
                oskar_gaussian_cuda_d(oskar_mem_double2(beam, status),
                        num_points, l_, m_, std);
            }
            else
            {
                oskar_gaussian_cuda_md(oskar_mem_double4c(beam, status),
                        num_points, l_, m_, std);
            }
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
    }
    else /* type == OSKAR_SINGLE */
    {
        const float *l_, *m_;
        l_ = oskar_mem_float_const(l, status);
        m_ = oskar_mem_float_const(m, status);

        if (location == OSKAR_CPU)
        {
            if (oskar_mem_is_scalar(beam))
            {
                oskar_gaussian_f(oskar_mem_float2(beam, status), num_points,
                        l_, m_, (float)std);
            }
            else
            {
                oskar_gaussian_mf(oskar_mem_float4c(beam, status), num_points,
                        l_, m_, (float)std);
            }
        }
        else
        {
#ifdef OSKAR_HAVE_CUDA
            if (oskar_mem_is_scalar(beam))
            {
                oskar_gaussian_cuda_f(oskar_mem_float2(beam, status),
                        num_points, l_, m_, (float)std);
            }
            else
            {
                oskar_gaussian_cuda_mf(oskar_mem_float4c(beam, status),
                        num_points, l_, m_, (float)std);
            }
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
    }

    /* Blank (zero) sources below the horizon. */
    oskar_blank_below_horizon(beam, horizon_mask, num_points, status);
}
예제 #30
0
void oskar_vis_block_write_ms(const oskar_VisBlock* blk,
        const oskar_VisHeader* header, oskar_MeasurementSet* ms, int* status)
{
    const oskar_Mem *in_acorr, *in_xcorr, *in_uu, *in_vv, *in_ww;
    oskar_Mem *temp_vis = 0, *temp_uu = 0, *temp_vv = 0, *temp_ww = 0;
    double exposure_sec, interval_sec, t_start_mjd, t_start_sec;
    double ra_rad, dec_rad, ref_freq_hz;
    unsigned int a1, a2, num_baseln_in, num_baseln_out, num_channels;
    unsigned int num_pols_in, num_pols_out, num_stations, num_times, b, c, t;
    unsigned int i, i_out, prec, start_time_index, start_chan_index;
    unsigned int have_autocorr, have_crosscorr;
    const void *xcorr, *acorr;
    void* out;

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

    /* Pull data from visibility structures. */
    num_pols_out     = oskar_ms_num_pols(ms);
    num_pols_in      = oskar_vis_block_num_pols(blk);
    num_stations     = oskar_vis_block_num_stations(blk);
    num_baseln_in    = oskar_vis_block_num_baselines(blk);
    num_channels     = oskar_vis_block_num_channels(blk);
    num_times        = oskar_vis_block_num_times(blk);
    in_acorr         = oskar_vis_block_auto_correlations_const(blk);
    in_xcorr         = oskar_vis_block_cross_correlations_const(blk);
    in_uu            = oskar_vis_block_baseline_uu_metres_const(blk);
    in_vv            = oskar_vis_block_baseline_vv_metres_const(blk);
    in_ww            = oskar_vis_block_baseline_ww_metres_const(blk);
    have_autocorr    = oskar_vis_block_has_auto_correlations(blk);
    have_crosscorr   = oskar_vis_block_has_cross_correlations(blk);
    start_time_index = oskar_vis_block_start_time_index(blk);
    start_chan_index = oskar_vis_block_start_channel_index(blk);
    ra_rad           = oskar_vis_header_phase_centre_ra_deg(header) * D2R;
    dec_rad          = oskar_vis_header_phase_centre_dec_deg(header) * D2R;
    exposure_sec     = oskar_vis_header_time_average_sec(header);
    interval_sec     = oskar_vis_header_time_inc_sec(header);
    t_start_mjd      = oskar_vis_header_time_start_mjd_utc(header);
    ref_freq_hz      = oskar_vis_header_freq_start_hz(header);
    prec             = oskar_mem_precision(in_xcorr);
    t_start_sec      = t_start_mjd * 86400.0 +
            interval_sec * (start_time_index + 0.5);

    /* Check that there is something to write. */
    if (!have_autocorr && !have_crosscorr) return;

    /* Get number of output baselines. */
    num_baseln_out = num_baseln_in;
    if (have_autocorr)
        num_baseln_out += num_stations;

    /* Check polarisation dimension consistency:
     * num_pols_in can be less than num_pols_out, but not vice-versa. */
    if (num_pols_in > num_pols_out)
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }

    /* Check the dimensions match. */
    if (oskar_ms_num_pols(ms) != num_pols_out ||
            oskar_ms_num_stations(ms) != num_stations)
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }

    /* Check the reference frequencies match. */
    if (fabs(oskar_ms_ref_freq_hz(ms) - ref_freq_hz) > 1e-10)
    {
        *status = OSKAR_ERR_VALUE_MISMATCH;
        return;
    }

    /* Check the phase centres are the same. */
    if (fabs(oskar_ms_phase_centre_ra_rad(ms) - ra_rad) > 1e-10 ||
            fabs(oskar_ms_phase_centre_dec_rad(ms) - dec_rad) > 1e-10)
    {
        *status = OSKAR_ERR_VALUE_MISMATCH;
        return;
    }

    /* Add visibilities and u,v,w coordinates. */
    temp_vis = oskar_mem_create(prec | OSKAR_COMPLEX, OSKAR_CPU,
            num_baseln_out * num_channels * num_pols_out, status);
    temp_uu = oskar_mem_create(prec, OSKAR_CPU, num_baseln_out, status);
    temp_vv = oskar_mem_create(prec, OSKAR_CPU, num_baseln_out, status);
    temp_ww = oskar_mem_create(prec, OSKAR_CPU, num_baseln_out, status);
    xcorr   = oskar_mem_void_const(in_xcorr);
    acorr   = oskar_mem_void_const(in_acorr);
    out     = oskar_mem_void(temp_vis);
    if (prec == OSKAR_DOUBLE)
    {
        const double *uu_in, *vv_in, *ww_in;
        double *uu_out, *vv_out, *ww_out;
        uu_in = oskar_mem_double_const(in_uu, status);
        vv_in = oskar_mem_double_const(in_vv, status);
        ww_in = oskar_mem_double_const(in_ww, status);
        uu_out = oskar_mem_double(temp_uu, status);
        vv_out = oskar_mem_double(temp_vv, status);
        ww_out = oskar_mem_double(temp_ww, status);
        for (t = 0; t < num_times; ++t)
        {
            /* Construct the baseline coordinates for the given time. */
            int start_row = (start_time_index + t) * num_baseln_out;
            for (a1 = 0, b = 0, i_out = 0; a1 < num_stations; ++a1)
            {
                if (have_autocorr)
                {
                    uu_out[i_out] = 0.0;
                    vv_out[i_out] = 0.0;
                    ww_out[i_out] = 0.0;
                    ++i_out;
                }
                if (have_crosscorr)
                {
                    for (a2 = a1 + 1; a2 < num_stations; ++a2, ++b, ++i_out)
                    {
                        i = num_baseln_in * t + b;
                        uu_out[i_out] = uu_in[i];
                        vv_out[i_out] = vv_in[i];
                        ww_out[i_out] = ww_in[i];
                    }
                }
            }

            for (c = 0, i_out = 0; c < num_channels; ++c)
            {
                /* Construct amplitude data for the given time and channel. */
                if (num_pols_in == 4)
                {
                    for (a1 = 0, b = 0; a1 < num_stations; ++a1)
                    {
                        if (have_autocorr)
                        {
                            i = num_stations * (t * num_channels + c) + a1;
                            ((double4c*)out)[i_out++] =
                                    ((const double4c*)acorr)[i];
                        }
                        if (have_crosscorr)
                        {
                            for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2)
                            {
                                i = num_baseln_in * (t * num_channels + c) + b;
                                ((double4c*)out)[i_out++] =
                                        ((const double4c*)xcorr)[i];
                            }
                        }
                    }
                }
                else if (num_pols_in == 1 && num_pols_out == 1)
                {
                    for (a1 = 0, b = 0; a1 < num_stations; ++a1)
                    {
                        if (have_autocorr)
                        {
                            i = num_stations * (t * num_channels + c) + a1;
                            ((double2*)out)[i_out++] =
                                    ((const double2*)acorr)[i];
                        }
                        if (have_crosscorr)
                        {
                            for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2)
                            {
                                i = num_baseln_in * (t * num_channels + c) + b;
                                ((double2*)out)[i_out++] =
                                        ((const double2*)xcorr)[i];
                            }
                        }
                    }
                }
                else
                {
                    double2 vis_amp, *out_;
                    out_ = (double2*)out;
                    for (a1 = 0, b = 0; a1 < num_stations; ++a1)
                    {
                        if (have_autocorr)
                        {
                            i = num_stations * (t * num_channels + c) + a1;
                            vis_amp = ((const double2*)acorr)[i];
                            out_[i_out + 0] = vis_amp;  /* XX */
                            out_[i_out + 1].x = 0.0;    /* XY */
                            out_[i_out + 1].y = 0.0;    /* XY */
                            out_[i_out + 2].x = 0.0;    /* YX */
                            out_[i_out + 2].y = 0.0;    /* YX */
                            out_[i_out + 3] = vis_amp;  /* YY */
                            i_out += 4;
                        }
                        if (have_crosscorr)
                        {
                            for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2)
                            {
                                i = num_baseln_in * (t * num_channels + c) + b;
                                vis_amp = ((const double2*)xcorr)[i];
                                out_[i_out + 0] = vis_amp;  /* XX */
                                out_[i_out + 1].x = 0.0;    /* XY */
                                out_[i_out + 1].y = 0.0;    /* XY */
                                out_[i_out + 2].x = 0.0;    /* YX */
                                out_[i_out + 2].y = 0.0;    /* YX */
                                out_[i_out + 3] = vis_amp;  /* YY */
                                i_out += 4;
                            }
                        }
                    }
                }
            }
            oskar_ms_write_coords_d(ms, start_row, num_baseln_out,
                    uu_out, vv_out, ww_out, exposure_sec, interval_sec,
                    t_start_sec + (t * interval_sec));
            oskar_ms_write_vis_d(ms, start_row, start_chan_index,
                    num_channels, num_baseln_out, (const double*)out);
        }
    }
    else if (prec == OSKAR_SINGLE)
    {
        const float *uu_in, *vv_in, *ww_in;
        float *uu_out, *vv_out, *ww_out;
        uu_in = oskar_mem_float_const(in_uu, status);
        vv_in = oskar_mem_float_const(in_vv, status);
        ww_in = oskar_mem_float_const(in_ww, status);
        uu_out = oskar_mem_float(temp_uu, status);
        vv_out = oskar_mem_float(temp_vv, status);
        ww_out = oskar_mem_float(temp_ww, status);
        for (t = 0; t < num_times; ++t)
        {
            /* Construct the baseline coordinates for the given time. */
            int start_row = (start_time_index + t) * num_baseln_out;
            for (a1 = 0, b = 0, i_out = 0; a1 < num_stations; ++a1)
            {
                if (have_autocorr)
                {
                    uu_out[i_out] = 0.0;
                    vv_out[i_out] = 0.0;
                    ww_out[i_out] = 0.0;
                    ++i_out;
                }
                if (have_crosscorr)
                {
                    for (a2 = a1 + 1; a2 < num_stations; ++a2, ++b, ++i_out)
                    {
                        i = num_baseln_in * t + b;
                        uu_out[i_out] = uu_in[i];
                        vv_out[i_out] = vv_in[i];
                        ww_out[i_out] = ww_in[i];
                    }
                }
            }

            for (c = 0, i_out = 0; c < num_channels; ++c)
            {
                /* Construct amplitude data for the given time and channel. */
                if (num_pols_in == 4)
                {
                    for (a1 = 0, b = 0; a1 < num_stations; ++a1)
                    {
                        if (have_autocorr)
                        {
                            i = num_stations * (t * num_channels + c) + a1;
                            ((float4c*)out)[i_out++] =
                                    ((const float4c*)acorr)[i];
                        }
                        if (have_crosscorr)
                        {
                            for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2)
                            {
                                i = num_baseln_in * (t * num_channels + c) + b;
                                ((float4c*)out)[i_out++] =
                                        ((const float4c*)xcorr)[i];
                            }
                        }
                    }
                }
                else if (num_pols_in == 1 && num_pols_out == 1)
                {
                    for (a1 = 0, b = 0; a1 < num_stations; ++a1)
                    {
                        if (have_autocorr)
                        {
                            i = num_stations * (t * num_channels + c) + a1;
                            ((float2*)out)[i_out++] =
                                    ((const float2*)acorr)[i];
                        }
                        if (have_crosscorr)
                        {
                            for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2)
                            {
                                i = num_baseln_in * (t * num_channels + c) + b;
                                ((float2*)out)[i_out++] =
                                        ((const float2*)xcorr)[i];
                            }
                        }
                    }
                }
                else
                {
                    float2 vis_amp, *out_;
                    out_ = (float2*)out;
                    for (a1 = 0, b = 0; a1 < num_stations; ++a1)
                    {
                        if (have_autocorr)
                        {
                            i = num_stations * (t * num_channels + c) + a1;
                            vis_amp = ((const float2*)acorr)[i];
                            out_[i_out + 0] = vis_amp;  /* XX */
                            out_[i_out + 1].x = 0.0;    /* XY */
                            out_[i_out + 1].y = 0.0;    /* XY */
                            out_[i_out + 2].x = 0.0;    /* YX */
                            out_[i_out + 2].y = 0.0;    /* YX */
                            out_[i_out + 3] = vis_amp;  /* YY */
                            i_out += 4;
                        }
                        if (have_crosscorr)
                        {
                            for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2)
                            {
                                i = num_baseln_in * (t * num_channels + c) + b;
                                vis_amp = ((const float2*)xcorr)[i];
                                out_[i_out + 0] = vis_amp;  /* XX */
                                out_[i_out + 1].x = 0.0;    /* XY */
                                out_[i_out + 1].y = 0.0;    /* XY */
                                out_[i_out + 2].x = 0.0;    /* YX */
                                out_[i_out + 2].y = 0.0;    /* YX */
                                out_[i_out + 3] = vis_amp;  /* YY */
                                i_out += 4;
                            }
                        }
                    }
                }
            }
            oskar_ms_write_coords_f(ms, start_row, num_baseln_out,
                    uu_out, vv_out, ww_out, exposure_sec, interval_sec,
                    t_start_sec + (t * interval_sec));
            oskar_ms_write_vis_f(ms, start_row, start_chan_index,
                    num_channels, num_baseln_out, (const float*)out);
        }
    }
    else
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
    }

    /* Cleanup. */
    oskar_mem_free(temp_vis, status);
    oskar_mem_free(temp_uu, status);
    oskar_mem_free(temp_vv, status);
    oskar_mem_free(temp_ww, status);
}