Exemple #1
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;
    }
}
Exemple #2
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];
        }
    }
}
Exemple #3
0
TEST(Mem, set_value_real_double_complex)
{
    // Double precision complex.
    int n = 100, status = 0;
    oskar_Mem *mem, *mem2;
    mem = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU, n,
            &status);
    oskar_mem_set_value_real(mem, 6.5, 0, 0, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    mem2 = oskar_mem_create_copy(mem, OSKAR_CPU, &status);
    double2* v = oskar_mem_double2(mem2, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    for (int i = 0; i < n; ++i)
    {
        EXPECT_DOUBLE_EQ(v[i].x, 6.5);
        EXPECT_DOUBLE_EQ(v[i].y, 0.0);
    }
    oskar_mem_free(mem, &status);
    oskar_mem_free(mem2, &status);
}
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);
    }
}
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);
    }
}
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;
    }
}
Exemple #7
0
TEST(imager, grid_sum)
{
    int status = 0, type = OSKAR_DOUBLE;
    int size = 2048, grid_size = size * size;

    // Create and set up the imager.
    oskar_Imager* im = oskar_imager_create(type, &status);
    oskar_imager_set_grid_kernel(im, "pillbox", 1, 1, &status);
    oskar_imager_set_fov(im, 5.0);
    oskar_imager_set_size(im, size, &status);
    oskar_Mem* grid = oskar_mem_create(type | OSKAR_COMPLEX, OSKAR_CPU,
            grid_size, &status);
    ASSERT_EQ(0, status);

    // Create visibility data.
    int num_vis = 10000;
    oskar_Mem* uu = oskar_mem_create(type, OSKAR_CPU, num_vis, &status);
    oskar_Mem* vv = oskar_mem_create(type, OSKAR_CPU, num_vis, &status);
    oskar_Mem* ww = oskar_mem_create(type, OSKAR_CPU, num_vis, &status);
    oskar_Mem* vis = oskar_mem_create(type | OSKAR_COMPLEX, OSKAR_CPU, num_vis,
            &status);
    oskar_Mem* weight = oskar_mem_create(type, OSKAR_CPU, num_vis, &status);
    oskar_mem_random_gaussian(uu, 0, 1, 2, 3, 100.0, &status);
    oskar_mem_random_gaussian(vv, 4, 5, 6, 7, 100.0, &status);
    oskar_mem_set_value_real(vis, 1.0, 0, num_vis, &status);
    oskar_mem_set_value_real(weight, 1.0, 0, num_vis, &status);

    // Grid visibility data.
    double plane_norm = 0.0;
    oskar_imager_update_plane(im, num_vis, uu, vv, ww, vis, weight, grid,
            &plane_norm, 0, &status);
    ASSERT_DOUBLE_EQ((double)num_vis, plane_norm);

    // Sum the grid.
    double2* t = oskar_mem_double2(grid, &status);
    double sum = 0.0;
    for (int i = 0; i < grid_size; i++) sum += t[i].x;
    ASSERT_DOUBLE_EQ((double)num_vis, sum);

    // Finalise the image.
    oskar_imager_finalise_plane(im, grid, plane_norm, &status);
    ASSERT_EQ(0, status);

#ifdef WRITE_FITS
    // Get the real part only.
    if (oskar_mem_precision(grid) == OSKAR_DOUBLE)
    {
        double *t = oskar_mem_double(grid, &status);
        for (int j = 0; j < grid_size; ++j) t[j] = t[2 * j];
    }
    else
    {
        float *t = oskar_mem_float(grid, &status);
        for (int j = 0; j < grid_size; ++j) t[j] = t[2 * j];
    }

    // Save the real part.
    fitsfile* f;
    long naxes[2] = {size, size}, firstpix[2] = {1, 1};
    fits_create_file(&f, "test_imager_grid_sum.fits", &status);
    fits_create_img(f, (type == OSKAR_DOUBLE ? DOUBLE_IMG : FLOAT_IMG),
            2, naxes, &status);
    fits_write_pix(f, (type == OSKAR_DOUBLE ? TDOUBLE : TFLOAT),
            firstpix, grid_size, oskar_mem_void(grid), &status);
    fits_close_file(f, &status);
#endif

    // Clean up.
    oskar_imager_free(im, &status);
    oskar_mem_free(uu, &status);
    oskar_mem_free(vv, &status);
    oskar_mem_free(ww, &status);
    oskar_mem_free(vis, &status);
    oskar_mem_free(weight, &status);
    oskar_mem_free(grid, &status);
}
/* 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;
}
void oskar_mem_add_real(oskar_Mem* mem, double val, int* status)
{
    int precision, location;
    size_t i, num_elements;

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

    /* Get meta-data. */
    precision = oskar_mem_precision(mem);
    location = oskar_mem_location(mem);

    /* Check for empty array. */
    num_elements = oskar_mem_length(mem);
    if (num_elements == 0)
        return;

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

    /* Get total number of elements to add. */
    if (oskar_mem_is_matrix(mem))
        num_elements *= 4;

    /* Switch on type and location. */
    if (oskar_mem_is_complex(mem))
    {
        if (precision == OSKAR_DOUBLE)
        {
            double2 *t;
            t = oskar_mem_double2(mem, status);
            for (i = 0; i < num_elements; ++i) t[i].x += val;
        }
        else if (precision == OSKAR_SINGLE)
        {
            float2 *t;
            t = oskar_mem_float2(mem, status);
            for (i = 0; i < num_elements; ++i) t[i].x += val;
        }
        else
        {
            *status = OSKAR_ERR_BAD_DATA_TYPE;
        }
    }
    else
    {
        if (precision == OSKAR_DOUBLE)
        {
            double *t;
            t = oskar_mem_double(mem, status);
            for (i = 0; i < num_elements; ++i) t[i] += val;
        }
        else if (precision == OSKAR_SINGLE)
        {
            float *t;
            t = oskar_mem_float(mem, status);
            for (i = 0; i < num_elements; ++i) t[i] += val;
        }
        else
        {
            *status = OSKAR_ERR_BAD_DATA_TYPE;
        }
    }
}
Exemple #10
0
void oskar_imager_filter_uv(const oskar_Imager* h, size_t* num_vis,
        oskar_Mem* uu, oskar_Mem* vv, oskar_Mem* ww, oskar_Mem* amp,
        oskar_Mem* weight, int* status)
{
    size_t i, n;
    double r, range[2];

    /* Return immediately if filtering is not enabled. */
    if (h->uv_filter_min <= 0.0 && h->uv_filter_max < 0.0) return;
    if (*status) return;

    /* Get the range (squared, to avoid lots of square roots later). */
    range[0] = h->uv_filter_min;
    range[1] = (h->uv_filter_max < 0.0) ? (double) FLT_MAX : h->uv_filter_max;
    range[0] *= range[0];
    range[1] *= range[1];

    /* Get the number of input points, and set the number selected to zero. */
    n = *num_vis;
    *num_vis = 0;

    /* Apply the UV baseline length filter. */
    if (h->imager_prec == OSKAR_DOUBLE)
    {
        double *uu_, *vv_, *ww_, *weight_;
        double2* amp_;
        uu_ = oskar_mem_double(uu, status);
        vv_ = oskar_mem_double(vv, status);
        ww_ = oskar_mem_double(ww, status);
        amp_ = oskar_mem_double2(amp, status);
        weight_ = oskar_mem_double(weight, status);

        for (i = 0; i < n; ++i)
        {
            r = uu_[i] * uu_[i] + vv_[i] * vv_[i];
            if (r >= range[0] && r <= range[1])
            {
                uu_[*num_vis] = uu_[i];
                vv_[*num_vis] = vv_[i];
                ww_[*num_vis] = ww_[i];
                amp_[*num_vis] = amp_[i];
                weight_[*num_vis] = weight_[i];
                (*num_vis)++;
            }
        }
    }
    else
    {
        float *uu_, *vv_, *ww_, *weight_;
        float2* amp_;
        uu_ = oskar_mem_float(uu, status);
        vv_ = oskar_mem_float(vv, status);
        ww_ = oskar_mem_float(ww, status);
        amp_ = oskar_mem_float2(amp, status);
        weight_ = oskar_mem_float(weight, status);

        for (i = 0; i < n; ++i)
        {
            r = uu_[i] * uu_[i] + vv_[i] * vv_[i];
            if (r >= range[0] && r <= range[1])
            {
                uu_[*num_vis] = uu_[i];
                vv_[*num_vis] = vv_[i];
                ww_[*num_vis] = ww_[i];
                amp_[*num_vis] = amp_[i];
                weight_[*num_vis] = weight_[i];
                (*num_vis)++;
            }
        }
    }
}
Exemple #11
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);
}
Exemple #12
0
TEST(element_weights_errors, test_apply)
{
    int num_elements   = 10000;
    int status = 0;

    double gain        = 1.5;
    double gain_error  = 0.2;
    double phase       = 0.1 * M_PI;
    double phase_error = (5 / 180.0) * M_PI;

    double weight_gain  = 1.0;
    double weight_phase = 0.5 * M_PI;

    double2 weight;
    weight.x = weight_gain * cos(weight_phase);
    weight.y = weight_gain * sin(weight_phase);

    oskar_Mem *d_gain, *d_gain_error, *d_phase, *d_phase_error, *d_errors;
    oskar_Mem *h_weights, *d_weights;
    d_errors = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU,
            num_elements, &status);
    d_gain = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_gain_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_phase = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_phase_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    h_weights = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU,
            num_elements, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    oskar_mem_set_value_real(d_gain, gain, 0, 0, &status);
    oskar_mem_set_value_real(d_gain_error, gain_error, 0, 0, &status);
    oskar_mem_set_value_real(d_phase, phase, 0, 0, &status);
    oskar_mem_set_value_real(d_phase_error, phase_error, 0, 0, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    double2* h_weights_ = oskar_mem_double2(h_weights, &status);
    for (int i = 0; i < num_elements; ++i)
    {
        h_weights_[i].x = weight.x;
        h_weights_[i].y = weight.y;
    }
    d_weights = oskar_mem_create_copy(h_weights, OSKAR_GPU, &status);

    oskar_evaluate_element_weights_errors(num_elements,
            d_gain, d_gain_error, d_phase, d_phase_error,
            0, 0, 0, d_errors, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    oskar_mem_element_multiply(NULL, d_weights, d_errors, num_elements, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Write memory to file for inspection.
    const char* fname = "temp_test_weights.dat";
    FILE* file = fopen(fname, "w");
    oskar_mem_save_ascii(file, 7, num_elements, &status,
            d_gain, d_gain_error, d_phase, d_phase_error, d_errors,
            h_weights, d_weights);
    fclose(file);
    remove(fname);

    // Free memory.
    oskar_mem_free(d_gain, &status);
    oskar_mem_free(d_gain_error, &status);
    oskar_mem_free(d_phase, &status);
    oskar_mem_free(d_phase_error, &status);
    oskar_mem_free(d_errors, &status);
    oskar_mem_free(h_weights, &status);
    oskar_mem_free(d_weights, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
}
Exemple #13
0
TEST(element_weights_errors, test_reinit)
{
    int num_elements   = 5;
    int status = 0;

    double gain        = 1.5;
    double gain_error  = 0.2;
    double phase       = 0.1 * M_PI;
    double phase_error = (5 / 180.0) * M_PI;

    oskar_Mem *d_errors, *d_gain, *d_gain_error, *d_phase, *d_phase_error;
    d_errors = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU,
            num_elements, &status);
    d_gain = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_gain_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_phase = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_phase_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    oskar_mem_set_value_real(d_gain, gain, 0, 0, &status);
    oskar_mem_set_value_real(d_gain_error, gain_error, 0, 0, &status);
    oskar_mem_set_value_real(d_phase, phase, 0, 0, &status);
    oskar_mem_set_value_real(d_phase_error, phase_error, 0, 0, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    int num_channels = 2;
    int num_chunks = 3;
    int num_stations = 5;
    int num_times = 3;
    unsigned int seed = 1;

    const char* fname = "temp_test_weights_error_reinit.dat";
    FILE* file = fopen(fname, "w");
    for (int chan = 0; chan < num_channels; ++chan)
    {
        fprintf(file, "channel: %i\n", chan);
        for (int chunk = 0; chunk < num_chunks; ++chunk)
        {
            fprintf(file, "  chunk: %i\n", chunk);
            ASSERT_EQ(0, status) << oskar_get_error_string(status);

            for (int t = 0; t < num_times; ++t)
            {
                fprintf(file, "    time: %i\n", t);
                for (int s = 0; s < num_stations; ++s)
                {
                    fprintf(file, "      station: %i  ==> ", s);
                    oskar_evaluate_element_weights_errors(num_elements,
                            d_gain, d_gain_error, d_phase, d_phase_error,
                            seed, t, s, d_errors, &status);
                    ASSERT_EQ(0, status) << oskar_get_error_string(status);
                    oskar_Mem *h_errors = oskar_mem_create_copy(d_errors,
                            OSKAR_CPU, &status);
                    double2* errors = oskar_mem_double2(h_errors, &status);
                    for (int i = 0; i < num_elements; ++i)
                    {
                        fprintf(file, "(% -6.4f, % -6.4f), ",
                                errors[i].x, errors[i].y);
                    }
                    fprintf(file, "\n");
                    oskar_mem_free(h_errors, &status);
                }
            }
            ASSERT_EQ(0, status) << oskar_get_error_string(status);
        }
    }
    fclose(file);
//    remove(fname);

    oskar_mem_free(d_gain, &status);
    oskar_mem_free(d_gain_error, &status);
    oskar_mem_free(d_phase, &status);
    oskar_mem_free(d_phase_error, &status);
    oskar_mem_free(d_errors, &status);
}
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);
    }
}
Exemple #15
0
TEST(binary_file, binary_read_write_mem)
{
    const char filename[] = "temp_test_mem_binary.dat";
    int num_cpu = 1000;
    int num_gpu = 2048;
    int status = 0;

    // Create the handle.
    oskar_Binary* h = oskar_binary_create(filename, 'w', &status);

    // Save data from CPU.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU,
                num_cpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        float* data = oskar_mem_float(mem, &status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 1024.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "USER", "TEST", 987654, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_mem_free(mem, &status);
    }

    // Save data from GPU.
    {
        oskar_Mem *mem_cpu, *mem_gpu;
        mem_cpu = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU,
                num_gpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        double2* data = oskar_mem_double2(mem_cpu, &status);

        // Fill array with data.
        for (int i = 0; i < num_gpu; ++i)
        {
            data[i].x = i * 10.0;
            data[i].y = i * 20.0 + 1.0;
        }

        // Copy data to GPU.
        mem_gpu = oskar_mem_create_copy(mem_cpu, OSKAR_GPU, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Save GPU data.
        oskar_binary_write_mem_ext(h, mem_gpu, "AA", "BB", 2, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_mem_free(mem_cpu, &status);
        oskar_mem_free(mem_gpu, &status);
    }

    // Save a single integer with a large index.
    int val = 0xFFFFFF;
    oskar_binary_write_int(h, 50, 9, 800000, val, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Save data from CPU with blank tags.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU,
                num_cpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        double* data = oskar_mem_double(mem, &status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 500.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "", "", 10, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 501.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "", "", 11, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_mem_free(mem, &status);
    }

    // Save CPU data with tags that are equal lengths.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU,
                num_cpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        double* data = oskar_mem_double(mem, &status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 1001.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "DOG", "CAT", 0, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 127.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "ONE", "TWO", 0, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_mem_free(mem, &status);
    }

    // Create the handle for reading.
    oskar_binary_free(h);
    h = oskar_binary_create(filename, 'r', &status);

    // Load data directly to GPU.
    {
        oskar_Mem *mem_gpu, *mem_cpu;
        mem_gpu = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU,
                0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem_gpu, "AA", "BB", 2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        EXPECT_EQ(num_gpu, (int)oskar_mem_length(mem_gpu));

        // Copy back to CPU and examine contents.
        mem_cpu = oskar_mem_create_copy(mem_gpu, OSKAR_CPU, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        double2* data = oskar_mem_double2(mem_cpu, &status);
        for (int i = 0; i < num_gpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 10.0,       data[i].x);
            EXPECT_DOUBLE_EQ(i * 20.0 + 1.0, data[i].y);
        }
        oskar_mem_free(mem_cpu, &status);
        oskar_mem_free(mem_gpu, &status);
    }

    // Load integer with a large index.
    int new_val = 0;
    oskar_binary_read_int(h, 50, 9, 800000, &new_val, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    EXPECT_EQ(val, new_val);

    // Load CPU data.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU,
                num_cpu, &status);
        oskar_binary_read_mem_ext(h, mem, "USER", "TEST", 987654, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        float* data = oskar_mem_float(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 1024.0, data[i]);
        }
        oskar_mem_free(mem, &status);
    }

    // Load CPU data with blank tags.
    {
        double* data;
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU,
                num_cpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem, "", "", 10, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem, "DOESN'T", "EXIST", 10, &status);
        EXPECT_EQ((int)OSKAR_ERR_BINARY_TAG_NOT_FOUND, status);
        status = 0;
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        data = oskar_mem_double(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 500.0, data[i]);
        }
        oskar_binary_read_mem_ext(h, mem, "", "", 11, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        data = oskar_mem_double(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 501.0, data[i]);
        }
        oskar_mem_free(mem, &status);
    }

    // Load CPU data with tags that are equal lengths.
    {
        double* data;
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0,
                &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem, "ONE", "TWO", 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        data = oskar_mem_double(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 127.0, data[i]);
        }
        oskar_binary_read_mem_ext(h, mem, "DOG", "CAT", 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        data = oskar_mem_double(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 1001.0, data[i]);
        }
        oskar_mem_free(mem, &status);
    }

    // Try to load data that isn't present.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0,
                &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem, "DOESN'T", "EXIST", 10, &status);
        EXPECT_EQ((int)OSKAR_ERR_BINARY_TAG_NOT_FOUND, status);
        status = 0;
        EXPECT_EQ(0, (int)oskar_mem_length(mem));
        oskar_mem_free(mem, &status);
    }

    // Release the handle.
    oskar_binary_free(h);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
}
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);
    }
}
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_);
            }
        }
    }
}
Exemple #18
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);
}
/* Wrapper. */
void oskar_evaluate_cross_power(int num_sources,
        int num_stations, const oskar_Mem* jones, oskar_Mem* out,
        int *status)
{
    int type, location;

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

    /* Check type and location. */
    type = oskar_mem_type(jones);
    location = oskar_mem_location(jones);
    if (type != oskar_mem_type(out))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }
    if (location != oskar_mem_location(out))
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }

    /* Switch on type and location combination. */
    if (type == OSKAR_SINGLE_COMPLEX_MATRIX)
    {
        if (location == OSKAR_GPU)
        {
#ifdef OSKAR_HAVE_CUDA
            oskar_evaluate_cross_power_cuda_f(num_sources,
                    num_stations, oskar_mem_float4c_const(jones, status),
                    oskar_mem_float4c(out, status));
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
        else if (location == OSKAR_CPU)
        {
            oskar_evaluate_cross_power_omp_f(num_sources,
                    num_stations, oskar_mem_float4c_const(jones, status),
                    oskar_mem_float4c(out, status));
        }
    }
    else if (type == OSKAR_DOUBLE_COMPLEX_MATRIX)
    {
        if (location == OSKAR_GPU)
        {
#ifdef OSKAR_HAVE_CUDA
            oskar_evaluate_cross_power_cuda_d(num_sources,
                    num_stations, oskar_mem_double4c_const(jones, status),
                    oskar_mem_double4c(out, status));
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
        else if (location == OSKAR_CPU)
        {
            oskar_evaluate_cross_power_omp_d(num_sources,
                    num_stations, oskar_mem_double4c_const(jones, status),
                    oskar_mem_double4c(out, status));
        }
    }

    /* Scalar versions. */
    else if (type == OSKAR_SINGLE_COMPLEX)
    {
        if (location == OSKAR_GPU)
        {
#ifdef OSKAR_HAVE_CUDA
            oskar_evaluate_cross_power_scalar_cuda_f(num_sources,
                    num_stations, oskar_mem_float2_const(jones, status),
                    oskar_mem_float2(out, status));
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
        else if (location == OSKAR_CPU)
        {
            oskar_evaluate_cross_power_scalar_omp_f(num_sources,
                    num_stations, oskar_mem_float2_const(jones, status),
                    oskar_mem_float2(out, status));
        }
    }
    else if (type == OSKAR_DOUBLE_COMPLEX)
    {
        if (location == OSKAR_GPU)
        {
#ifdef OSKAR_HAVE_CUDA
            oskar_evaluate_cross_power_scalar_cuda_d(num_sources,
                    num_stations, oskar_mem_double2_const(jones, status),
                    oskar_mem_double2(out, status));
            oskar_device_check_error(status);
#else
            *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        }
        else if (location == OSKAR_CPU)
        {
            oskar_evaluate_cross_power_scalar_omp_d(num_sources,
                    num_stations, oskar_mem_double2_const(jones, status),
                    oskar_mem_double2(out, status));
        }
    }
    else
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
    }
}