/* Wrapper. */ void oskar_evaluate_jones_K(oskar_Jones* K, int num_sources, const oskar_Mem* l, const oskar_Mem* m, const oskar_Mem* n, const oskar_Mem* u, const oskar_Mem* v, const oskar_Mem* w, double frequency_hz, const oskar_Mem* source_filter, double source_filter_min, double source_filter_max, int* status) { int num_stations, jones_type, base_type, location; double wavenumber; /* Check if safe to proceed. */ if (*status) return; /* Get the Jones matrix block meta-data. */ jones_type = oskar_jones_type(K); base_type = oskar_type_precision(jones_type); location = oskar_jones_mem_location(K); num_stations = oskar_jones_num_stations(K); wavenumber = 2.0 * M_PI * frequency_hz / 299792458.0; /* Check that the data is in the right location. */ if (oskar_mem_location(l) != location || oskar_mem_location(m) != location || oskar_mem_location(n) != location || oskar_mem_location(source_filter) != location || oskar_mem_location(u) != location || oskar_mem_location(v) != location || oskar_mem_location(w) != location) { *status = OSKAR_ERR_LOCATION_MISMATCH; return; } /* Check that the data are of the right type. */ if (!oskar_type_is_complex(jones_type) || oskar_type_is_matrix(jones_type)) { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } if (base_type != oskar_mem_type(l) || base_type != oskar_mem_type(m) || base_type != oskar_mem_type(n) || base_type != oskar_mem_type(u) || base_type != oskar_mem_type(v) || base_type != oskar_mem_type(w) || base_type != oskar_mem_type(source_filter)) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } /* Evaluate Jones matrices. */ if (location == OSKAR_GPU) { #ifdef OSKAR_HAVE_CUDA if (jones_type == OSKAR_SINGLE_COMPLEX) { oskar_evaluate_jones_K_cuda_f(oskar_jones_float2(K, status), num_sources, oskar_mem_float_const(l, status), oskar_mem_float_const(m, status), oskar_mem_float_const(n, status), num_stations, oskar_mem_float_const(u, status), oskar_mem_float_const(v, status), oskar_mem_float_const(w, status), wavenumber, oskar_mem_float_const(source_filter, status), source_filter_min, source_filter_max); } else if (jones_type == OSKAR_DOUBLE_COMPLEX) { oskar_evaluate_jones_K_cuda_d(oskar_jones_double2(K, status), num_sources, oskar_mem_double_const(l, status), oskar_mem_double_const(m, status), oskar_mem_double_const(n, status), num_stations, oskar_mem_double_const(u, status), oskar_mem_double_const(v, status), oskar_mem_double_const(w, status), wavenumber, oskar_mem_double_const(source_filter, status), source_filter_min, source_filter_max); } oskar_device_check_error(status); #else *status = OSKAR_ERR_CUDA_NOT_AVAILABLE; #endif } else if (location == OSKAR_CPU) { if (jones_type == OSKAR_SINGLE_COMPLEX) { oskar_evaluate_jones_K_f(oskar_jones_float2(K, status), num_sources, oskar_mem_float_const(l, status), oskar_mem_float_const(m, status), oskar_mem_float_const(n, status), num_stations, oskar_mem_float_const(u, status), oskar_mem_float_const(v, status), oskar_mem_float_const(w, status), wavenumber, oskar_mem_float_const(source_filter, status), source_filter_min, source_filter_max); } else if (jones_type == OSKAR_DOUBLE_COMPLEX) { oskar_evaluate_jones_K_d(oskar_jones_double2(K, status), num_sources, oskar_mem_double_const(l, status), oskar_mem_double_const(m, status), oskar_mem_double_const(n, status), num_stations, oskar_mem_double_const(u, status), oskar_mem_double_const(v, status), oskar_mem_double_const(w, status), wavenumber, oskar_mem_double_const(source_filter, status), source_filter_min, source_filter_max); } } }
void oskar_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; }
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; } }
/* Wrapper. */ void oskar_convert_enu_directions_to_theta_phi(int num_points, const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z, double delta_phi, oskar_Mem* theta, oskar_Mem* phi, int* status) { int type, location; /* Check if safe to proceed. */ if (*status) return; /* Get data type and location. */ type = oskar_mem_type(theta); location = oskar_mem_location(theta); /* Compute modified theta and phi coordinates. */ if (location == OSKAR_GPU) { #ifdef OSKAR_HAVE_CUDA if (type == OSKAR_SINGLE) { oskar_convert_enu_directions_to_theta_phi_cuda_f(num_points, oskar_mem_float_const(x, status), oskar_mem_float_const(y, status), oskar_mem_float_const(z, status), (float)delta_phi, oskar_mem_float(theta, status), oskar_mem_float(phi, status)); oskar_device_check_error(status); } else if (type == OSKAR_DOUBLE) { oskar_convert_enu_directions_to_theta_phi_cuda_d(num_points, oskar_mem_double_const(x, status), oskar_mem_double_const(y, status), oskar_mem_double_const(z, status), delta_phi, oskar_mem_double(theta, status), oskar_mem_double(phi, status)); oskar_device_check_error(status); } else *status = OSKAR_ERR_BAD_DATA_TYPE; #else *status = OSKAR_ERR_CUDA_NOT_AVAILABLE; #endif } else if (location == OSKAR_CPU) { if (type == OSKAR_SINGLE) { oskar_convert_enu_directions_to_theta_phi_f(num_points, oskar_mem_float_const(x, status), oskar_mem_float_const(y, status), oskar_mem_float_const(z, status), (float)delta_phi, oskar_mem_float(theta, status), oskar_mem_float(phi, status)); } else if (type == OSKAR_DOUBLE) { oskar_convert_enu_directions_to_theta_phi_d(num_points, oskar_mem_double_const(x, status), oskar_mem_double_const(y, status), oskar_mem_double_const(z, status), delta_phi, oskar_mem_double(theta, status), oskar_mem_double(phi, status)); } else *status = OSKAR_ERR_BAD_DATA_TYPE; } }
void oskar_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; } }
/* 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); }