void oskar_fft_exec(oskar_FFT* h, oskar_Mem* data, int* status) { oskar_Mem *data_copy = 0, *data_ptr = data; if (oskar_mem_location(data) != h->location) { data_copy = oskar_mem_create_copy(data, h->location, status); data_ptr = data_copy; } if (h->location == OSKAR_CPU) { if (h->num_dim == 1) { *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE; } else if (h->num_dim == 2) { if (h->precision == OSKAR_DOUBLE) oskar_fftpack_cfft2f(h->dim_size, h->dim_size, h->dim_size, oskar_mem_double(data_ptr, status), oskar_mem_double(h->fftpack_wsave, status), oskar_mem_double(h->fftpack_work, status)); else oskar_fftpack_cfft2f_f(h->dim_size, h->dim_size, h->dim_size, oskar_mem_float(data_ptr, status), oskar_mem_float(h->fftpack_wsave, status), oskar_mem_float(h->fftpack_work, status)); /* This step not needed for W-kernel generation, so turn it off. */ if (h->ensure_consistent_norm) oskar_mem_scale_real(data_ptr, (double)h->num_cells_total, 0, h->num_cells_total, status); } } else if (h->location == OSKAR_GPU) { #ifdef OSKAR_HAVE_CUDA if (h->precision == OSKAR_DOUBLE) cufftExecZ2Z(h->cufft_plan, (cufftDoubleComplex*) oskar_mem_void(data_ptr), (cufftDoubleComplex*) oskar_mem_void(data_ptr), CUFFT_FORWARD); else cufftExecC2C(h->cufft_plan, (cufftComplex*) oskar_mem_void(data_ptr), (cufftComplex*) oskar_mem_void(data_ptr), CUFFT_FORWARD); #endif } else *status = OSKAR_ERR_BAD_LOCATION; if (oskar_mem_location(data) != h->location) oskar_mem_copy(data, data_ptr, status); oskar_mem_free(data_copy, status); }
int oskar_find_closest_match(double value, const oskar_Mem* values, int* status) { int type, num_values, match_index = 0; /* Check if safe to proceed. */ if (*status) return 0; /* Check location. */ if (oskar_mem_location(values) != OSKAR_CPU) { *status = OSKAR_ERR_BAD_LOCATION; return 0; } /* Switch on type. */ type = oskar_mem_type(values); num_values = (int)oskar_mem_length(values); if (type == OSKAR_DOUBLE) { match_index = oskar_find_closest_match_d(value, num_values, oskar_mem_double_const(values, status)); } else if (type == OSKAR_SINGLE) { match_index = oskar_find_closest_match_f(value, num_values, oskar_mem_float_const(values, status)); } else { *status = OSKAR_ERR_BAD_DATA_TYPE; } return match_index; }
void oskar_convert_station_uvw_to_baseline_uvw(int num_stations, int offset_in, const oskar_Mem* u, const oskar_Mem* v, const oskar_Mem* w, int offset_out, oskar_Mem* uu, oskar_Mem* vv, oskar_Mem* ww, int* status) { if (*status) return; const int type = oskar_mem_type(u); const int location = oskar_mem_location(u); if (location == OSKAR_CPU) { if (type == OSKAR_SINGLE) convert_station_uvw_to_baseline_uvw_float(num_stations, offset_in, oskar_mem_float_const(u, status), oskar_mem_float_const(v, status), oskar_mem_float_const(w, status), offset_out, oskar_mem_float(uu, status), oskar_mem_float(vv, status), oskar_mem_float(ww, status)); else if (type == OSKAR_DOUBLE) convert_station_uvw_to_baseline_uvw_double(num_stations, offset_in, oskar_mem_double_const(u, status), oskar_mem_double_const(v, status), oskar_mem_double_const(w, status), offset_out, oskar_mem_double(uu, status), oskar_mem_double(vv, status), oskar_mem_double(ww, status)); else *status = OSKAR_ERR_BAD_DATA_TYPE; } else { size_t local_size[] = {32, 1, 1}, global_size[] = {1, 1, 1}; const char* k = 0; if (type == OSKAR_SINGLE) k = "convert_station_uvw_to_baseline_uvw_float"; else if (type == OSKAR_DOUBLE) k = "convert_station_uvw_to_baseline_uvw_double"; else { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } oskar_device_check_local_size(location, 0, local_size); global_size[0] = num_stations * local_size[0]; const oskar_Arg args[] = { {INT_SZ, &num_stations}, {INT_SZ, &offset_in}, {PTR_SZ, oskar_mem_buffer_const(u)}, {PTR_SZ, oskar_mem_buffer_const(v)}, {PTR_SZ, oskar_mem_buffer_const(w)}, {INT_SZ, &offset_out}, {PTR_SZ, oskar_mem_buffer(uu)}, {PTR_SZ, oskar_mem_buffer(vv)}, {PTR_SZ, oskar_mem_buffer(ww)} }; oskar_device_launch_kernel(k, location, 1, local_size, global_size, sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status); } }
void oskar_binary_read_mem_ext(oskar_Binary* handle, oskar_Mem* mem, const char* name_group, const char* name_tag, int user_index, int* status) { int type; oskar_Mem *temp = 0, *data = 0; size_t size_bytes = 0, element_size = 0; /* Check if safe to proceed. */ if (*status) return; /* Get the data type. */ type = oskar_mem_type(mem); /* Initialise temporary (to zero length). */ temp = oskar_mem_create(type, OSKAR_CPU, 0, status); /* Check if data is in CPU or GPU memory. */ data = (oskar_mem_location(mem) == OSKAR_CPU) ? mem : temp; /* Query the tag index to find out how big the block is. */ element_size = oskar_mem_element_size(type); oskar_binary_query_ext(handle, (unsigned char)type, name_group, name_tag, user_index, &size_bytes, status); /* Resize memory block if necessary, so that it can hold the data. */ oskar_mem_realloc(data, size_bytes / element_size, status); /* Load the memory. */ oskar_binary_read_ext(handle, (unsigned char)type, name_group, name_tag, user_index, size_bytes, oskar_mem_void(data), status); /* Copy to GPU memory if required. */ if (oskar_mem_location(mem) != OSKAR_CPU) oskar_mem_copy(mem, temp, status); /* Free the temporary. */ oskar_mem_free(temp, status); }
void oskar_mem_multiply( oskar_Mem* out, const oskar_Mem* in1, const oskar_Mem* in2, size_t offset_out, size_t offset_in1, size_t offset_in2, size_t num_elements, int* status) { oskar_Mem *a_temp = 0, *b_temp = 0; const oskar_Mem *a_, *b_; /* Pointers. */ if (num_elements == 0) return; const int location = oskar_mem_location(out); const unsigned int off_a = (unsigned int) offset_in1; const unsigned int off_b = (unsigned int) offset_in2; const unsigned int off_c = (unsigned int) offset_out; const unsigned int n = (unsigned int) num_elements; if (*status) return; a_ = in1; b_ = in2; if (oskar_mem_location(in1) != location) { a_temp = oskar_mem_create_copy(in1, location, status); a_ = a_temp; } if (oskar_mem_location(in2) != location) { b_temp = oskar_mem_create_copy(in2, location, status); b_ = b_temp; } if (location == OSKAR_CPU) { void *c = out->data; const void *a = a_->data, *b = b_->data; /* Check if types are all the same. */ if (out->type == in1->type && out->type == in2->type) { switch (out->type) { case OSKAR_DOUBLE: mem_mul_rr_r_double(off_a, off_b, off_c, n, (const double*)a, (const double*)b, (double*)c); break; case OSKAR_DOUBLE_COMPLEX: mem_mul_cc_c_double(off_a, off_b, off_c, n, (const double2*)a, (const double2*)b, (double2*)c); break; case OSKAR_DOUBLE_COMPLEX_MATRIX: mem_mul_mm_m_double(off_a, off_b, off_c, n, (const double4c*)a, (const double4c*)b, (double4c*)c); break; case OSKAR_SINGLE: mem_mul_rr_r_float(off_a, off_b, off_c, n, (const float*)a, (const float*)b, (float*)c); break; case OSKAR_SINGLE_COMPLEX: mem_mul_cc_c_float(off_a, off_b, off_c, n, (const float2*)a, (const float2*)b, (float2*)c); break; case OSKAR_SINGLE_COMPLEX_MATRIX: mem_mul_mm_m_float(off_a, off_b, off_c, n, (const float4c*)a, (const float4c*)b, (float4c*)c); break; default: *status = OSKAR_ERR_BAD_DATA_TYPE; break; } } else { switch (out->type) { case OSKAR_DOUBLE_COMPLEX_MATRIX: { switch (in1->type) { case OSKAR_DOUBLE_COMPLEX: if (in2->type == in1->type) mem_mul_cc_m_double(off_a, off_b, off_c, n, (const double2*)a, (const double2*)b, (double4c*)c); else if (in2->type == out->type) mem_mul_cm_m_double(off_a, off_b, off_c, n, (const double2*)a, (const double4c*)b, (double4c*)c); else *status = OSKAR_ERR_TYPE_MISMATCH; break; case OSKAR_DOUBLE_COMPLEX_MATRIX: if (in2->type == OSKAR_DOUBLE_COMPLEX) mem_mul_mc_m_double(off_a, off_b, off_c, n, (const double4c*)a, (const double2*)b, (double4c*)c); else *status = OSKAR_ERR_TYPE_MISMATCH; break; default: *status = OSKAR_ERR_TYPE_MISMATCH; break; } break; } case OSKAR_SINGLE_COMPLEX_MATRIX: { switch (in1->type) { case OSKAR_SINGLE_COMPLEX: if (in2->type == in1->type) mem_mul_cc_m_float(off_a, off_b, off_c, n, (const float2*)a, (const float2*)b, (float4c*)c); else if (in2->type == out->type) mem_mul_cm_m_float(off_a, off_b, off_c, n, (const float2*)a, (const float4c*)b, (float4c*)c); else *status = OSKAR_ERR_TYPE_MISMATCH; break; case OSKAR_SINGLE_COMPLEX_MATRIX: if (in2->type == OSKAR_SINGLE_COMPLEX) mem_mul_mc_m_float(off_a, off_b, off_c, n, (const float4c*)a, (const float2*)b, (float4c*)c); else *status = OSKAR_ERR_TYPE_MISMATCH; break; default: *status = OSKAR_ERR_TYPE_MISMATCH; break; } break; } default: *status = OSKAR_ERR_TYPE_MISMATCH; break; } } } else { const char* k = 0; /* Check if types are all the same. */ if (out->type == in1->type && out->type == in2->type) { switch (out->type) { case OSKAR_DOUBLE: k = "mem_mul_rr_r_double"; break; case OSKAR_DOUBLE_COMPLEX: k = "mem_mul_cc_c_double"; break; case OSKAR_DOUBLE_COMPLEX_MATRIX: k = "mem_mul_mm_m_double"; break; case OSKAR_SINGLE: k = "mem_mul_rr_r_float"; break; case OSKAR_SINGLE_COMPLEX: k = "mem_mul_cc_c_float"; break; case OSKAR_SINGLE_COMPLEX_MATRIX: k = "mem_mul_mm_m_float"; break; default: *status = OSKAR_ERR_BAD_DATA_TYPE; break; } } else { switch (out->type) { case OSKAR_DOUBLE_COMPLEX_MATRIX: { switch (in1->type) { case OSKAR_DOUBLE_COMPLEX: if (in2->type == in1->type) k = "mem_mul_cc_m_double"; else if (in2->type == out->type) k = "mem_mul_cm_m_double"; else *status = OSKAR_ERR_TYPE_MISMATCH; break; case OSKAR_DOUBLE_COMPLEX_MATRIX: if (in2->type == OSKAR_DOUBLE_COMPLEX) k = "mem_mul_mc_m_double"; else *status = OSKAR_ERR_TYPE_MISMATCH; break; default: *status = OSKAR_ERR_TYPE_MISMATCH; break; } break; } case OSKAR_SINGLE_COMPLEX_MATRIX: { switch (in1->type) { case OSKAR_SINGLE_COMPLEX: if (in2->type == in1->type) k = "mem_mul_cc_m_float"; else if (in2->type == out->type) k = "mem_mul_cm_m_float"; else *status = OSKAR_ERR_TYPE_MISMATCH; break; case OSKAR_SINGLE_COMPLEX_MATRIX: if (in2->type == OSKAR_SINGLE_COMPLEX) k = "mem_mul_mc_m_float"; else *status = OSKAR_ERR_TYPE_MISMATCH; break; default: *status = OSKAR_ERR_TYPE_MISMATCH; break; } break; } default: *status = OSKAR_ERR_TYPE_MISMATCH; break; } } if (!*status) { size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1}; oskar_device_check_local_size(location, 0, local_size); global_size[0] = oskar_device_global_size( num_elements, local_size[0]); const oskar_Arg args[] = { {INT_SZ, &off_a}, {INT_SZ, &off_b}, {INT_SZ, &off_c}, {INT_SZ, &n}, {PTR_SZ, oskar_mem_buffer_const(a_)}, {PTR_SZ, oskar_mem_buffer_const(b_)}, {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); } } /* Free temporary arrays. */ oskar_mem_free(a_temp, status); oskar_mem_free(b_temp, 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); } }
/* 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; } }
void oskar_splines_evaluate(const oskar_Splines* spline, int num_points, const oskar_Mem* x, const oskar_Mem* y, int stride_out, int offset_out, oskar_Mem* output, int* status) { if (*status) return; const int type = oskar_splines_precision(spline); const int location = oskar_splines_mem_location(spline); const int nx = oskar_splines_num_knots_x_theta(spline); const int ny = oskar_splines_num_knots_y_phi(spline); const oskar_Mem* tx = oskar_splines_knots_x_theta_const(spline); const oskar_Mem* ty = oskar_splines_knots_y_phi_const(spline); const oskar_Mem* coeff = oskar_splines_coeff_const(spline); if (type != oskar_mem_type(x) || type != oskar_mem_type(y)) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } if (location != oskar_mem_location(output) || location != oskar_mem_location(x) || location != oskar_mem_location(y)) { *status = OSKAR_ERR_LOCATION_MISMATCH; return; } if (location == OSKAR_CPU) { int i; if (type == OSKAR_SINGLE) { const float *tx_, *ty_, *coeff_, *x_, *y_; float *out; tx_ = oskar_mem_float_const(tx, status); ty_ = oskar_mem_float_const(ty, status); coeff_ = oskar_mem_float_const(coeff, status); x_ = oskar_mem_float_const(x, status); y_ = oskar_mem_float_const(y, status); out = oskar_mem_float(output, status) + offset_out; if (nx == 0 || ny == 0 || !tx_ || !ty_ || !coeff_) for (i = 0; i < num_points; ++i) out[i * stride_out] = 0.0f; else { float x1, y1, wrk[8]; int iwrk1[2], kwrk1 = 2, lwrk = 8, err = 0; for (i = 0; i < num_points; ++i) { x1 = x_[i]; y1 = y_[i]; oskar_dierckx_bispev_f(tx_, nx, ty_, ny, coeff_, 3, 3, &x1, 1, &y1, 1, &out[i * stride_out], wrk, lwrk, iwrk1, kwrk1, &err); if (err != 0) { *status = OSKAR_ERR_SPLINE_EVAL_FAIL; return; } } } } else if (type == OSKAR_DOUBLE) { const double *tx_, *ty_, *coeff_, *x_, *y_; double *out; tx_ = oskar_mem_double_const(tx, status); ty_ = oskar_mem_double_const(ty, status); coeff_ = oskar_mem_double_const(coeff, status); x_ = oskar_mem_double_const(x, status); y_ = oskar_mem_double_const(y, status); out = oskar_mem_double(output, status) + offset_out; if (nx == 0 || ny == 0 || !tx_ || !ty_ || !coeff_) for (i = 0; i < num_points; ++i) out[i * stride_out] = 0.0; else { double x1, y1, wrk[8]; int iwrk1[2], kwrk1 = 2, lwrk = 8, err = 0; for (i = 0; i < num_points; ++i) { x1 = x_[i]; y1 = y_[i]; oskar_dierckx_bispev_d(tx_, nx, ty_, ny, coeff_, 3, 3, &x1, 1, &y1, 1, &out[i * stride_out], wrk, lwrk, iwrk1, kwrk1, &err); if (err != 0) { *status = OSKAR_ERR_SPLINE_EVAL_FAIL; return; } } } } else *status = OSKAR_ERR_BAD_DATA_TYPE; } else { size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1}; const char* k = 0; if (nx == 0 || ny == 0) { if (type == OSKAR_DOUBLE) k = "set_zeros_stride_double"; else if (type == OSKAR_SINGLE) k = "set_zeros_stride_float"; else { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } oskar_device_check_local_size(location, 0, local_size); global_size[0] = oskar_device_global_size( (size_t) num_points, local_size[0]); const oskar_Arg args[] = { {INT_SZ, &num_points}, {INT_SZ, &stride_out}, {INT_SZ, &offset_out}, {PTR_SZ, oskar_mem_buffer(output)} }; oskar_device_launch_kernel(k, location, 1, local_size, global_size, sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status); } else { if (type == OSKAR_DOUBLE) k = "dierckx_bispev_bicubic_double"; else if (type == OSKAR_SINGLE) k = "dierckx_bispev_bicubic_float"; else { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } oskar_device_check_local_size(location, 0, local_size); global_size[0] = oskar_device_global_size( (size_t) num_points, local_size[0]); const oskar_Arg args[] = { {PTR_SZ, oskar_mem_buffer_const(tx)}, {INT_SZ, &nx}, {PTR_SZ, oskar_mem_buffer_const(ty)}, {INT_SZ, &ny}, {PTR_SZ, oskar_mem_buffer_const(coeff)}, {INT_SZ, &num_points}, {PTR_SZ, oskar_mem_buffer_const(x)}, {PTR_SZ, oskar_mem_buffer_const(y)}, {INT_SZ, &stride_out}, {INT_SZ, &offset_out}, {PTR_SZ, oskar_mem_buffer(output)} }; oskar_device_launch_kernel(k, location, 1, local_size, global_size, sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status); } } }
void oskar_mem_evaluate_relative_error(const oskar_Mem* val_approx, const oskar_Mem* val_accurate, double* min_rel_error, double* max_rel_error, double* avg_rel_error, double* std_rel_error, int* status) { int prec_approx, prec_accurate; size_t i, n; const oskar_Mem *app_ptr, *acc_ptr; oskar_Mem *approx_temp = 0, *accurate_temp = 0; double old_m = 0.0, new_m = 0.0, old_s = 0.0, new_s = 0.0; /* Check if safe to proceed. */ if (*status) return; /* Initialise outputs. */ if (max_rel_error) *max_rel_error = -DBL_MAX; if (min_rel_error) *min_rel_error = DBL_MAX; if (avg_rel_error) *avg_rel_error = DBL_MAX; if (std_rel_error) *std_rel_error = DBL_MAX; /* Type and dimension check. */ if (oskar_mem_is_matrix(val_approx) && !oskar_mem_is_matrix(val_accurate)) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } if (oskar_mem_is_complex(val_approx) && !oskar_mem_is_complex(val_accurate)) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } /* Get and check base types. */ prec_approx = oskar_mem_precision(val_approx); prec_accurate = oskar_mem_precision(val_accurate); if (prec_approx != OSKAR_SINGLE && prec_approx != OSKAR_DOUBLE) { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } if (prec_accurate != OSKAR_SINGLE && prec_accurate != OSKAR_DOUBLE) { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } /* Get number of elements to check. */ n = oskar_mem_length(val_approx) < oskar_mem_length(val_accurate) ? oskar_mem_length(val_approx) : oskar_mem_length(val_accurate); if (oskar_mem_is_matrix(val_approx)) n *= 4; /* Copy input data to temporary CPU arrays if required. */ app_ptr = val_approx; acc_ptr = val_accurate; if (oskar_mem_location(val_approx) != OSKAR_CPU) { approx_temp = oskar_mem_create_copy(val_approx, OSKAR_CPU, status); if (*status) { oskar_mem_free(approx_temp, status); return; } app_ptr = approx_temp; } if (oskar_mem_location(val_accurate) != OSKAR_CPU) { accurate_temp = oskar_mem_create_copy(val_accurate, OSKAR_CPU, status); if (*status) { oskar_mem_free(accurate_temp, status); return; } acc_ptr = accurate_temp; } /* Check numbers are the same, to appropriate precision. */ if (prec_approx == OSKAR_SINGLE && prec_accurate == OSKAR_SINGLE) { const float *approx, *accurate; approx = oskar_mem_float_const(app_ptr, status); accurate = oskar_mem_float_const(acc_ptr, status); CHECK_ELEMENTS(1e-5) } else if (prec_approx == OSKAR_DOUBLE && prec_accurate == OSKAR_SINGLE)
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_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; } } }
void oskar_mem_write_fits_cube(oskar_Mem* data, const char* root_name, int width, int height, int num_planes, int i_plane, int* status) { oskar_Mem *copy = 0, *ptr = 0; size_t len, buf_len; char* fname; /* Checks. */ if (*status) return; if (oskar_mem_is_matrix(data)) { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } /* Construct the filename. */ len = strlen(root_name); buf_len = 11 + len; fname = (char*) calloc(buf_len, sizeof(char)); /* Copy to host memory if necessary. */ ptr = data; if (oskar_mem_location(data) != OSKAR_CPU) { copy = oskar_mem_create_copy(ptr, OSKAR_CPU, status); ptr = copy; } /* Deal with complex data. */ if (oskar_mem_is_complex(ptr)) { oskar_Mem *temp; temp = oskar_mem_create(oskar_mem_precision(ptr), OSKAR_CPU, oskar_mem_length(ptr), status); /* Extract the real part and write it. */ SNPRINTF(fname, buf_len, "%s_REAL.fits", root_name); convert_complex(ptr, temp, 0, status); write_pixels(temp, fname, width, height, num_planes, i_plane, status); /* Extract the imaginary part and write it. */ SNPRINTF(fname, buf_len, "%s_IMAG.fits", root_name); convert_complex(ptr, temp, 1, status); write_pixels(temp, fname, width, height, num_planes, i_plane, status); oskar_mem_free(temp, status); } else { /* No conversion needed. */ if ((len >= 5) && ( !strcmp(&(root_name[len-5]), ".fits") || !strcmp(&(root_name[len-5]), ".FITS") )) { SNPRINTF(fname, buf_len, "%s", root_name); } else { SNPRINTF(fname, buf_len, "%s.fits", root_name); } write_pixels(ptr, fname, width, height, num_planes, i_plane, status); } free(fname); oskar_mem_free(copy, status); }
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); }
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); } }
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_mem_save_ascii(FILE* file, size_t num_mem, size_t offset, size_t num_elements, int* status, ...) { int type; size_t i, j; va_list args; oskar_Mem** handles; /* Array of oskar_Mem pointers in CPU memory. */ /* Check if safe to proceed. */ if (*status) return; /* Check there are at least the number of specified elements in * each array. */ va_start(args, status); for (i = 0; i < num_mem; ++i) { const oskar_Mem* mem; mem = va_arg(args, const oskar_Mem*); if (oskar_mem_length(mem) < num_elements) *status = OSKAR_ERR_DIMENSION_MISMATCH; } va_end(args); /* Check if safe to proceed. */ if (*status) return; /* Allocate and set up the handle array. */ handles = (oskar_Mem**) malloc(num_mem * sizeof(oskar_Mem*)); va_start(args, status); for (i = 0; i < num_mem; ++i) { oskar_Mem* mem; mem = va_arg(args, oskar_Mem*); if (oskar_mem_location(mem) != OSKAR_CPU) { handles[i] = oskar_mem_create_copy(mem, OSKAR_CPU, status); } else { handles[i] = mem; } } va_end(args); for (j = 0; j < num_elements; ++j) { /* Break if error. */ if (*status) break; for (i = 0; i < num_mem; ++i) { const void* data; data = oskar_mem_void_const(handles[i]); type = oskar_mem_type(handles[i]); switch (type) { case OSKAR_SINGLE: { fprintf(file, SDF, ((const float*)data)[j + offset]); continue; } case OSKAR_DOUBLE: { fprintf(file, SDD, ((const double*)data)[j + offset]); continue; } case OSKAR_SINGLE_COMPLEX: { float2 d; d = ((const float2*)data)[j + offset]; fprintf(file, SDF SDF, d.x, d.y); continue; } case OSKAR_DOUBLE_COMPLEX: { double2 d; d = ((const double2*)data)[j + offset]; fprintf(file, SDD SDD, d.x, d.y); continue; } case OSKAR_SINGLE_COMPLEX_MATRIX: { float4c d; d = ((const float4c*)data)[j + offset]; fprintf(file, SDF SDF SDF SDF SDF SDF SDF SDF, d.a.x, d.a.y, d.b.x, d.b.y, d.c.x, d.c.y, d.d.x, d.d.y); continue; } case OSKAR_DOUBLE_COMPLEX_MATRIX: { double4c d; d = ((const double4c*)data)[j + offset]; fprintf(file, SDD SDD SDD SDD SDD SDD SDD SDD, d.a.x, d.a.y, d.b.x, d.b.y, d.c.x, d.c.y, d.d.x, d.d.y); continue; } case OSKAR_CHAR: { putc(((const char*)data)[j + offset], file); continue; } case OSKAR_INT: { fprintf(file, "%5d ", ((const int*)data)[j + offset]); continue; } default: { *status = OSKAR_ERR_BAD_DATA_TYPE; continue; } } } putc('\n', file); } /* Free any temporary memory used by this function. */ va_start(args, status); for (i = 0; i < num_mem; ++i) { const oskar_Mem* mem; mem = va_arg(args, const oskar_Mem*); if (oskar_mem_location(mem) != OSKAR_CPU) { oskar_mem_free(handles[i], status); } } va_end(args); /* Free the handle array. */ free(handles); }
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_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; } }
int oskar_sph_rotate_to_position(int n, oskar_Mem* lon, oskar_Mem* lat, double lon0, double lat0) { int i; if (lon == NULL || lat == NULL) return OSKAR_ERR_INVALID_ARGUMENT; if (oskar_mem_location(lon) != OSKAR_CPU || oskar_mem_location(lat) != OSKAR_CPU) return OSKAR_ERR_BAD_LOCATION; if (oskar_mem_type(lon) == OSKAR_DOUBLE && oskar_mem_type(lat) == OSKAR_DOUBLE) { /* Construct rotation matrix. */ double cosLon, sinLon, cosLat, sinLat; double m11, m12, m13, m21, m22, m23, m31, m33; cosLon = cos(lon0); sinLon = sin(lon0); cosLat = cos(lat0); sinLat = sin(lat0); m11 = cosLon * sinLat; m12 = -sinLon; m13 = cosLon * cosLat; m21 = sinLon * sinLat; m22 = cosLon; m23 = sinLon * cosLat; m31 = -cosLat; m33 = sinLat; for (i = 0; i < n; ++i) { double x, y, z, a, b, c; /* Direction cosines */ c = cos(((double*)lat->data)[i]); x = c * cos(((double*)lon->data)[i]); y = c * sin(((double*)lon->data)[i]); z = sin(((double*)lat->data)[i]); /* Apply rotation matrix */ a = m11 * x + m12 * y + m13 * z; b = m21 * x + m22 * y + m23 * z; c = m31 * x + m33 * z; /* Convert back to angles. */ ((double*)lon->data)[i] = atan2(b, a); ((double*)lat->data)[i] = atan2(c, sqrt(a*a + b*b)); } } else if (oskar_mem_type(lon) == OSKAR_SINGLE && oskar_mem_type(lat) == OSKAR_SINGLE) { /* Construct rotation matrix. */ float cosLon, sinLon, cosLat, sinLat; float m11, m12, m13, m21, m22, m23, m31, m33; cosLon = cosf(lon0); sinLon = sinf(lon0); cosLat = cosf(lat0); sinLat = sinf(lat0); m11 = cosLon * sinLat; m12 = -sinLon; m13 = cosLon * cosLat; m21 = sinLon * sinLat; m22 = cosLon; m23 = sinLon * cosLat; m31 = -cosLat; m33 = sinLat; for (i = 0; i < n; ++i) { float x, y, z, a, b, c; /* Direction cosines */ c = cosf(((float*)lat->data)[i]); x = c * cosf(((float*)lon->data)[i]); y = c * sinf(((float*)lon->data)[i]); z = sinf(((float*)lat->data)[i]); /* Apply rotation matrix */ a = m11 * x + m12 * y + m13 * z; b = m21 * x + m22 * y + m23 * z; c = m31 * x + m33 * z; /* Convert back to angles. */ ((float*)lon->data)[i] = atan2f(b, a); ((float*)lat->data)[i] = atan2f(c, sqrtf(a*a + b*b)); } } else { return OSKAR_ERR_BAD_DATA_TYPE; } return 0; }
/* 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; }
/* 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; } }
/* 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_vla_beam_pbcor(oskar_Mem* beam, int num_sources, const oskar_Mem* l, const oskar_Mem* m, double frequency_hz, int* status) { int index, precision, type, location; double f, p1, p2, p3; /* Check if safe to proceed. */ if (*status) return; /* Check type and location. */ precision = oskar_mem_precision(beam); type = oskar_mem_type(beam); location = oskar_mem_location(beam); if (precision != oskar_mem_type(l) || precision != oskar_mem_type(m)) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } if (location != oskar_mem_location(l) || location != oskar_mem_location(m)) { *status = OSKAR_ERR_LOCATION_MISMATCH; return; } /* Find the nearest frequency at which data exists. */ index = oskar_find_closest_match_d(frequency_hz / 1.0e9, sizeof(freqs_ghz) / sizeof(double), freqs_ghz); f = frequency_hz / 1.0e9; p1 = p1s[index]; p2 = p2s[index]; p3 = p3s[index]; /* Switch on precision. */ if (precision == OSKAR_SINGLE) { const float *l_, *m_; l_ = oskar_mem_float_const(l, status); m_ = oskar_mem_float_const(m, status); if (location == OSKAR_GPU) { #ifdef OSKAR_HAVE_CUDA if (type == OSKAR_SINGLE) { oskar_evaluate_vla_beam_pbcor_cuda_f( oskar_mem_float(beam, status), num_sources, l_, m_, f, p1, p2, p3); } else if (type == OSKAR_SINGLE_COMPLEX) { oskar_evaluate_vla_beam_pbcor_complex_cuda_f( oskar_mem_float2(beam, status), num_sources, l_, m_, f, p1, p2, p3); } else if (type == OSKAR_SINGLE_COMPLEX_MATRIX) { oskar_evaluate_vla_beam_pbcor_matrix_cuda_f( oskar_mem_float4c(beam, status), num_sources, l_, m_, f, p1, p2, p3); } oskar_device_check_error(status); #else *status = OSKAR_ERR_CUDA_NOT_AVAILABLE; #endif } else if (location == OSKAR_CPU) { if (type == OSKAR_SINGLE) { oskar_evaluate_vla_beam_pbcor_f( oskar_mem_float(beam, status), num_sources, l_, m_, f, p1, p2, p3); } else if (type == OSKAR_SINGLE_COMPLEX) { oskar_evaluate_vla_beam_pbcor_complex_f( oskar_mem_float2(beam, status), num_sources, l_, m_, f, p1, p2, p3); } else if (type == OSKAR_SINGLE_COMPLEX_MATRIX) { oskar_evaluate_vla_beam_pbcor_matrix_f( oskar_mem_float4c(beam, status), num_sources, l_, m_, f, p1, p2, p3); } } } else if (precision == OSKAR_DOUBLE) { const double *l_, *m_; l_ = oskar_mem_double_const(l, status); m_ = oskar_mem_double_const(m, status); if (location == OSKAR_GPU) { #ifdef OSKAR_HAVE_CUDA if (type == OSKAR_DOUBLE) { oskar_evaluate_vla_beam_pbcor_cuda_d( oskar_mem_double(beam, status), num_sources, l_, m_, f, p1, p2, p3); } else if (type == OSKAR_DOUBLE_COMPLEX) { oskar_evaluate_vla_beam_pbcor_complex_cuda_d( oskar_mem_double2(beam, status), num_sources, l_, m_, f, p1, p2, p3); } else if (type == OSKAR_DOUBLE_COMPLEX_MATRIX) { oskar_evaluate_vla_beam_pbcor_matrix_cuda_d( oskar_mem_double4c(beam, status), num_sources, l_, m_, f, p1, p2, p3); } oskar_device_check_error(status); #else *status = OSKAR_ERR_CUDA_NOT_AVAILABLE; #endif } else if (location == OSKAR_CPU) { if (type == OSKAR_DOUBLE) { oskar_evaluate_vla_beam_pbcor_d( oskar_mem_double(beam, status), num_sources, l_, m_, f, p1, p2, p3); } else if (type == OSKAR_DOUBLE_COMPLEX) { oskar_evaluate_vla_beam_pbcor_complex_d( oskar_mem_double2(beam, status), num_sources, l_, m_, f, p1, p2, p3); } else if (type == OSKAR_DOUBLE_COMPLEX_MATRIX) { oskar_evaluate_vla_beam_pbcor_matrix_d( oskar_mem_double4c(beam, status), num_sources, l_, m_, f, p1, p2, p3); } } } else { *status = OSKAR_ERR_BAD_DATA_TYPE; } }
void oskar_evaluate_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_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); }