示例#1
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);
        }
    }
}
示例#2
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_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;
}
示例#4
0
void oskar_mem_realloc(oskar_Mem* mem, size_t num_elements, int* status)
{
    size_t element_size, new_size, old_size;

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

    /* Check if the structure owns the memory it points to. */
    if (mem->owner == 0)
    {
        *status = OSKAR_ERR_MEMORY_NOT_ALLOCATED;
        return;
    }

    /* Get size of new and old memory blocks. */
    element_size = oskar_mem_element_size(mem->type);
    if (element_size == 0)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    new_size = num_elements * element_size;
    old_size = mem->num_elements * element_size;

    /* Do nothing if new size and old size are the same. */
    if (new_size == old_size)
        return;

    /* Check memory location. */
    if (mem->location == OSKAR_CPU)
    {
        /* Reallocate the memory. */
        void* mem_new = NULL;
        mem_new = realloc(mem->data, new_size);
        if (!mem_new && (new_size > 0))
        {
            *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
            return;
        }

        /* Initialise the new memory if it's larger than the old block. */
        if (new_size > old_size)
            memset((char*)mem_new + old_size, 0, new_size - old_size);

        /* Set the new meta-data. */
        mem->data = (new_size > 0) ? mem_new : 0;
        mem->num_elements = num_elements;
    }
    else if (mem->location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        /* Allocate and initialise a new block of memory. */
        int cuda_error = 0;
        size_t copy_size;
        void* mem_new = NULL;
        if (new_size > 0)
        {
            cuda_error = cudaMalloc(&mem_new, new_size);
            if (cuda_error)
            {
                *status = cuda_error;
                return;
            }
            if (!mem_new)
            {
                *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
                return;
            }
        }

        /* Copy contents of old block to new block. */
        copy_size = (old_size > new_size) ? new_size : old_size;
        if (copy_size > 0)
        {
            cuda_error = cudaMemcpy(mem_new, mem->data, copy_size,
                    cudaMemcpyDeviceToDevice);
        }
        if (cuda_error)
        {
            *status = cuda_error;
            return;
        }

        /* Free the old block. */
        cudaFree(mem->data);
        oskar_device_check_error(status);

        /* Set the new meta-data. */
        mem->data = mem_new;
        mem->num_elements = num_elements;
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else
    {
        *status = OSKAR_ERR_BAD_LOCATION;
    }
}
void oskar_mem_realloc(oskar_Mem* mem, size_t num_elements, int* status)
{
    size_t element_size, new_size, old_size;

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

    /* Check if the structure owns the memory it points to. */
    if (mem->owner == 0)
    {
        *status = OSKAR_ERR_MEMORY_NOT_ALLOCATED;
        return;
    }

    /* Get size of new and old memory blocks. */
    element_size = oskar_mem_element_size(mem->type);
    if (element_size == 0)
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    new_size = num_elements * element_size;
    old_size = mem->num_elements * element_size;

    /* Do nothing if new size and old size are the same. */
    if (new_size == old_size)
        return;

    /* Check memory location. */
    if (mem->location == OSKAR_CPU)
    {
        /* Reallocate the memory. */
        void* mem_new = NULL;
        mem_new = realloc(mem->data, new_size);
        if (!mem_new && (new_size > 0))
        {
            *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
            return;
        }

        /* Initialise the new memory if it's larger than the old block. */
        if (new_size > old_size)
            memset((char*)mem_new + old_size, 0, new_size - old_size);

        /* Set the new meta-data. */
        mem->data = (new_size > 0) ? mem_new : 0;
        mem->num_elements = num_elements;
    }
    else if (mem->location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        /* Allocate and initialise a new block of memory. */
        int cuda_error = 0;
        size_t copy_size;
        void* mem_new = NULL;
        if (new_size > 0)
        {
            cuda_error = cudaMalloc(&mem_new, new_size);
            if (cuda_error)
            {
                *status = cuda_error;
                return;
            }
            if (!mem_new)
            {
                *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
                return;
            }
        }

        /* Copy contents of old block to new block. */
        copy_size = (old_size > new_size) ? new_size : old_size;
        if (copy_size > 0)
        {
            cuda_error = cudaMemcpy(mem_new, mem->data, copy_size,
                    cudaMemcpyDeviceToDevice);
        }
        if (cuda_error)
        {
            *status = cuda_error;
            return;
        }

        /* Free the old block. */
        cudaFree(mem->data);
        oskar_device_check_error(status);

        /* Set the new meta-data. */
        mem->data = mem_new;
        mem->num_elements = num_elements;
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else if (mem->location & OSKAR_CL)
    {
#ifdef OSKAR_HAVE_OPENCL
        /* Allocate and initialise a new block of memory. */
        cl_int error = 0;
        size_t copy_size;
        cl_mem mem_new;
        mem_new = clCreateBuffer(oskar_cl_context(),
                CL_MEM_READ_WRITE, new_size, NULL, &error);
        if (error != CL_SUCCESS)
        {
            *status = OSKAR_ERR_MEMORY_ALLOC_FAILURE;
            return;
        }

        /* Copy contents of old block to new block. */
        copy_size = (old_size > new_size) ? new_size : old_size;
        if (copy_size > 0)
        {
            error = clEnqueueCopyBuffer(oskar_cl_command_queue(), mem->buffer,
                    mem_new, 0, 0, copy_size, 0, NULL, NULL);
            if (error != CL_SUCCESS)
            {
                fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
                *status = OSKAR_ERR_MEMORY_COPY_FAILURE;
            }
        }

        /* Free the old buffer. */
        clReleaseMemObject(mem->buffer);

        /* Set the new meta-data. */
        mem->buffer = mem_new;
        mem->num_elements = num_elements;
#else
        *status = OSKAR_ERR_OPENCL_NOT_AVAILABLE;
#endif
    }
    else
    {
        *status = OSKAR_ERR_BAD_LOCATION;
    }
}
示例#6
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;
    }
}
示例#7
0
void oskar_mem_copy_contents(oskar_Mem* dst, const oskar_Mem* src,
        size_t offset_dst, size_t offset_src, size_t num_elements, int* status)
{
    int location_src, location_dst;
    size_t bytes, element_size, start_dst, start_src;
    void *destination;
    const void *source;

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

    /* Return immediately if there is nothing to copy. */
    if (src->data == NULL || src->num_elements == 0 || num_elements == 0)
        return;

    /* Check the data types. */
    if (src->type != dst->type)
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }

    /* Check the data dimensions. */
    if (num_elements > src->num_elements ||
            num_elements > (dst->num_elements - offset_dst))
    {
        *status = OSKAR_ERR_OUT_OF_RANGE;
        return;
    }

    /* Get the number of bytes to copy. */
    element_size = oskar_mem_element_size(src->type);
    bytes        = element_size * num_elements;
    start_dst    = element_size * offset_dst;
    start_src    = element_size * offset_src;
    destination  = (void*)((char*)(dst->data) + start_dst);
    source       = (const void*)((const char*)(src->data) + start_src);
    location_src = src->location;
    location_dst = dst->location;

    /* Host to host. */
    if (location_src == OSKAR_CPU && location_dst == OSKAR_CPU)
    {
        memcpy(destination, source, bytes);
        return;
    }

    /* Host to device. */
    else if (location_src == OSKAR_CPU && location_dst == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        cudaMemcpy(destination, source, bytes, cudaMemcpyHostToDevice);
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        return;
    }

    /* Device to host. */
    else if (location_src == OSKAR_GPU && location_dst == OSKAR_CPU)
    {
#ifdef OSKAR_HAVE_CUDA
        cudaMemcpy(destination, source, bytes, cudaMemcpyDeviceToHost);
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        return;
    }

    /* Device to device. */
    else if (location_src == OSKAR_GPU && location_dst == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        cudaMemcpy(destination, source, bytes, cudaMemcpyDeviceToDevice);
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
        return;
    }

    *status = OSKAR_ERR_BAD_LOCATION;
}
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;
    }
}
/* 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;
    }
}
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_);
            }
        }
    }
}
/* 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;
}
/* 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;
    }
}
示例#13
0
/* Wrapper. */
void oskar_evaluate_jones_R(oskar_Jones* R, int num_sources,
        const oskar_Mem* ra_rad, const oskar_Mem* dec_rad,
        const oskar_Telescope* telescope, double gast, int* status)
{
    int i, n, num_stations, jones_type, base_type, location;
    double latitude, lst;
    oskar_Mem *R_station;

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

    /* Get the Jones matrix block meta-data. */
    jones_type = oskar_jones_type(R);
    base_type = oskar_type_precision(jones_type);
    location = oskar_jones_mem_location(R);
    num_stations = oskar_jones_num_stations(R);
    n = (oskar_telescope_allow_station_beam_duplication(telescope) ? 1 : num_stations);

    /* Check that the data dimensions are OK. */
    if (num_sources > (int)oskar_mem_length(ra_rad) ||
            num_sources > (int)oskar_mem_length(dec_rad) ||
            num_sources > oskar_jones_num_sources(R) ||
            num_stations != oskar_telescope_num_stations(telescope))
    {
        *status = OSKAR_ERR_DIMENSION_MISMATCH;
        return;
    }

    /* Check that the data is in the right location. */
    if (location != oskar_mem_location(ra_rad) ||
            location != oskar_mem_location(dec_rad))
    {
        *status = OSKAR_ERR_LOCATION_MISMATCH;
        return;
    }

    /* Check that the data is of the right type. */
    if (!oskar_type_is_matrix(jones_type))
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    if (base_type != oskar_mem_precision(ra_rad) ||
            base_type != oskar_mem_precision(dec_rad))
    {
        *status = OSKAR_ERR_TYPE_MISMATCH;
        return;
    }

    /* Evaluate Jones matrix for each source for appropriate stations. */
    R_station = oskar_mem_create_alias(0, 0, 0, status);
    if (location == OSKAR_GPU)
    {
#ifdef OSKAR_HAVE_CUDA
        for (i = 0; i < n; ++i)
        {
            const oskar_Station* station;

            /* Get station data. */
            station = oskar_telescope_station_const(telescope, i);
            latitude = oskar_station_lat_rad(station);
            lst = gast + oskar_station_lon_rad(station);
            oskar_jones_get_station_pointer(R_station, R, i, status);

            /* Evaluate source parallactic angles. */
            if (base_type == OSKAR_SINGLE)
            {
                oskar_evaluate_jones_R_cuda_f(
                        oskar_mem_float4c(R_station, status), num_sources,
                        oskar_mem_float_const(ra_rad, status),
                        oskar_mem_float_const(dec_rad, status),
                        (float)latitude, (float)lst);
            }
            else if (base_type == OSKAR_DOUBLE)
            {
                oskar_evaluate_jones_R_cuda_d(
                        oskar_mem_double4c(R_station, status), num_sources,
                        oskar_mem_double_const(ra_rad, status),
                        oskar_mem_double_const(dec_rad, status),
                        latitude, lst);
            }
        }
        oskar_device_check_error(status);
#else
        *status = OSKAR_ERR_CUDA_NOT_AVAILABLE;
#endif
    }
    else if (location == OSKAR_CPU)
    {
        for (i = 0; i < n; ++i)
        {
            const oskar_Station* station;

            /* Get station data. */
            station = oskar_telescope_station_const(telescope, i);
            latitude = oskar_station_lat_rad(station);
            lst = gast + oskar_station_lon_rad(station);
            oskar_jones_get_station_pointer(R_station, R, i, status);

            /* Evaluate source parallactic angles. */
            if (base_type == OSKAR_SINGLE)
            {
                oskar_evaluate_jones_R_f(
                        oskar_mem_float4c(R_station, status), num_sources,
                        oskar_mem_float_const(ra_rad, status),
                        oskar_mem_float_const(dec_rad, status),
                        (float)latitude, (float)lst);
            }
            else if (base_type == OSKAR_DOUBLE)
            {
                oskar_evaluate_jones_R_d(
                        oskar_mem_double4c(R_station, status), num_sources,
                        oskar_mem_double_const(ra_rad, status),
                        oskar_mem_double_const(dec_rad, status),
                        latitude, lst);
            }
        }
    }

    /* Copy data for station 0 to stations 1 to n, if using a common sky. */
    if (oskar_telescope_allow_station_beam_duplication(telescope))
    {
        oskar_Mem* R0;
        R0 = oskar_mem_create_alias(0, 0, 0, status);
        oskar_jones_get_station_pointer(R0, R, 0, status);
        for (i = 1; i < num_stations; ++i)
        {
            oskar_jones_get_station_pointer(R_station, R, i, status);
            oskar_mem_copy_contents(R_station, R0, 0, 0,
                    oskar_mem_length(R0), status);
        }
        oskar_mem_free(R0, status);
    }
    oskar_mem_free(R_station, status);
}