void oskar_imager_update_plane_fft(oskar_Imager* h, int num_vis, const oskar_Mem* uu, const oskar_Mem* vv, const oskar_Mem* amps, const oskar_Mem* weight, oskar_Mem* plane, double* plane_norm, int* status) { int num_cells, num_skipped = 0; if (*status) return; num_cells = h->grid_size * h->grid_size; if (oskar_mem_precision(plane) != h->imager_prec) *status = OSKAR_ERR_TYPE_MISMATCH; if ((int)oskar_mem_length(plane) < num_cells) oskar_mem_realloc(plane, num_cells, status); if (*status) return; if (h->imager_prec == OSKAR_DOUBLE) oskar_grid_simple_d(h->support, h->oversample, oskar_mem_double_const(h->conv_func, status), num_vis, oskar_mem_double_const(uu, status), oskar_mem_double_const(vv, status), oskar_mem_double_const(amps, status), oskar_mem_double_const(weight, status), h->cellsize_rad, h->grid_size, &num_skipped, plane_norm, oskar_mem_double(plane, status)); else oskar_grid_simple_f(h->support, h->oversample, oskar_mem_double_const(h->conv_func, status), num_vis, oskar_mem_float_const(uu, status), oskar_mem_float_const(vv, status), oskar_mem_float_const(amps, status), oskar_mem_float_const(weight, status), h->cellsize_rad, h->grid_size, &num_skipped, plane_norm, oskar_mem_float(plane, status)); if (num_skipped > 0) printf("WARNING: Skipped %d visibility points.\n", num_skipped); }
void oskar_imager_trim_image(oskar_Mem* plane, int plane_size, int image_size, int* status) { int i, num_cells, size_diff; if (*status) return; /* Get the real part only, if the plane is complex. */ if (oskar_mem_is_complex(plane)) { num_cells = plane_size * plane_size; if (oskar_mem_precision(plane) == OSKAR_DOUBLE) { double *t = oskar_mem_double(plane, status); for (i = 0; i < num_cells; ++i) t[i] = t[2 * i]; } else { float *t = oskar_mem_float(plane, status); for (i = 0; i < num_cells; ++i) t[i] = t[2 * i]; } } /* Trim to required image size. */ size_diff = plane_size - image_size; if (size_diff > 0) { char *ptr; size_t in = 0, out = 0, copy_len = 0, element_size = 0; ptr = oskar_mem_char(plane); element_size = oskar_mem_element_size(oskar_mem_precision(plane)); copy_len = element_size * image_size; in = element_size * (size_diff / 2) * (plane_size + 1); for (i = 0; i < image_size; ++i) { /* Use memmove() instead of memcpy() to allow for overlap. */ memmove(ptr + out, ptr + in, copy_len); in += plane_size * element_size; out += copy_len; } } }
void oskar_imager_rotate_vis(size_t num_vis, const oskar_Mem* uu, const oskar_Mem* vv, const oskar_Mem* ww, oskar_Mem* amps, const double delta_l, const double delta_m, const double delta_n) { size_t i; if (oskar_mem_precision(amps) == OSKAR_DOUBLE) { const double *u, *v, *w; double2* a; u = (const double*)oskar_mem_void_const(uu); v = (const double*)oskar_mem_void_const(vv); w = (const double*)oskar_mem_void_const(ww); a = (double2*)oskar_mem_void(amps); for (i = 0; i < num_vis; ++i) { double arg, phase_re, phase_im, re, im; arg = 2.0*M_PI * (u[i] * delta_l + v[i] * delta_m + w[i] * delta_n); phase_re = cos(arg); phase_im = sin(arg); re = a[i].x * phase_re - a[i].y * phase_im; im = a[i].x * phase_im + a[i].y * phase_re; a[i].x = re; a[i].y = im; } } else { const float *u, *v, *w; float2* a; u = (const float*)oskar_mem_void_const(uu); v = (const float*)oskar_mem_void_const(vv); w = (const float*)oskar_mem_void_const(ww); a = (float2*)oskar_mem_void(amps); for (i = 0; i < num_vis; ++i) { float arg, phase_re, phase_im, re, im; arg = 2.0*M_PI * (u[i] * delta_l + v[i] * delta_m + w[i] * delta_n); phase_re = cos(arg); phase_im = sin(arg); re = a[i].x * phase_re - a[i].y * phase_im; im = a[i].x * phase_im + a[i].y * phase_re; a[i].x = re; a[i].y = im; } } }
void copy_vis_pol(oskar_Mem* amps, oskar_Mem* wt, int amps_offset, const oskar_Mem* vis, const oskar_Mem* weight, int vis_offset, int weight_offset, int num_baselines, int stride, int pol_offset, int* status) { int i; if (*status) return; if (oskar_mem_precision(amps) == OSKAR_SINGLE) { float* w_out; const float* w_in; w_out = oskar_mem_float(wt, status) + amps_offset; w_in = oskar_mem_float_const(weight, status); for (i = 0; i < num_baselines; ++i) w_out[i] = w_in[stride * (weight_offset + i) + pol_offset]; if (vis) { float2* a; const float2* v; a = oskar_mem_float2(amps, status) + amps_offset; v = oskar_mem_float2_const(vis, status); for (i = 0; i < num_baselines; ++i) a[i] = v[stride * (vis_offset + i) + pol_offset]; } } else { double* w_out; const double* w_in; w_out = oskar_mem_double(wt, status) + amps_offset; w_in = oskar_mem_double_const(weight, status); for (i = 0; i < num_baselines; ++i) w_out[i] = w_in[stride * (weight_offset + i) + pol_offset]; if (vis) { double2* a; const double2* v; a = oskar_mem_double2(amps, status) + amps_offset; v = oskar_mem_double2_const(vis, status); for (i = 0; i < num_baselines; ++i) a[i] = v[stride * (vis_offset + i) + pol_offset]; } } }
static void convert_complex(const oskar_Mem* input, oskar_Mem* output, int offset, int* status) { size_t i, num_elements; if (*status) return; num_elements = oskar_mem_length(input); if (oskar_mem_precision(input) == OSKAR_SINGLE) { const float *in; float *out; in = oskar_mem_float_const(input, status); out = oskar_mem_float(output, status); for (i = 0; i < num_elements; ++i) out[i] = in[2*i + offset]; } else { const double *in; double *out; in = oskar_mem_double_const(input, status); out = oskar_mem_double(output, status); for (i = 0; i < num_elements; ++i) out[i] = in[2*i + offset]; } }
void oskar_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_imager_finalise_plane(oskar_Imager* h, oskar_Mem* plane, double plane_norm, int* status) { int size, num_cells; DeviceData* d; if (*status) return; /* Apply normalisation. */ if (plane_norm > 0.0 || plane_norm < 0.0) oskar_mem_scale_real(plane, 1.0 / plane_norm, status); if (h->algorithm == OSKAR_ALGORITHM_DFT_2D || h->algorithm == OSKAR_ALGORITHM_DFT_3D) return; /* Check plane is complex type, as plane must be gridded visibilities. */ if (!oskar_mem_is_complex(plane)) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } /* Make image using FFT and apply grid correction. */ size = h->grid_size; num_cells = size * size; d = &h->d[0]; if (oskar_mem_precision(plane) == OSKAR_DOUBLE) { oskar_fftphase_cd(size, size, oskar_mem_double(plane, status)); if (h->fft_on_gpu) { #ifdef OSKAR_HAVE_CUDA oskar_device_set(h->cuda_device_ids[0], status); oskar_mem_copy(d->plane_gpu, plane, status); cufftExecZ2Z(h->cufft_plan, oskar_mem_void(d->plane_gpu), oskar_mem_void(d->plane_gpu), CUFFT_FORWARD); oskar_mem_copy(plane, d->plane_gpu, status); #else *status = OSKAR_ERR_CUDA_NOT_AVAILABLE; #endif } else { oskar_fftpack_cfft2f(size, size, size, oskar_mem_double(plane, status), oskar_mem_double(h->fftpack_wsave, status), oskar_mem_double(h->fftpack_work, status)); oskar_mem_scale_real(plane, (double)num_cells, status); } oskar_fftphase_cd(size, size, oskar_mem_double(plane, status)); oskar_grid_correction_d(size, oskar_mem_double(h->corr_func, status), oskar_mem_double(plane, status)); } else { oskar_fftphase_cf(size, size, oskar_mem_float(plane, status)); if (h->fft_on_gpu) { #ifdef OSKAR_HAVE_CUDA oskar_device_set(h->cuda_device_ids[0], status); oskar_mem_copy(d->plane_gpu, plane, status); cufftExecC2C(h->cufft_plan, oskar_mem_void(d->plane_gpu), oskar_mem_void(d->plane_gpu), CUFFT_FORWARD); oskar_mem_copy(plane, d->plane_gpu, status); #else *status = OSKAR_ERR_CUDA_NOT_AVAILABLE; #endif } else { oskar_fftpack_cfft2f_f(size, size, size, oskar_mem_float(plane, status), oskar_mem_float(h->fftpack_wsave, status), oskar_mem_float(h->fftpack_work, status)); oskar_mem_scale_real(plane, (double)num_cells, status); } oskar_fftphase_cf(size, size, oskar_mem_float(plane, status)); oskar_grid_correction_f(size, oskar_mem_double(h->corr_func, status), oskar_mem_float(plane, status)); } }
void oskar_gaussian_circular(int num_points, const oskar_Mem* l, const oskar_Mem* m, double std, oskar_Mem* out, int* status) { if (*status) return; const int location = oskar_mem_location(out); const double inv_2_var = 1.0 / (2.0 * std * std); const float inv_2_var_f = (float)inv_2_var; if (oskar_mem_precision(out) != oskar_mem_type(l) || oskar_mem_precision(out) != oskar_mem_type(m)) { *status = OSKAR_ERR_TYPE_MISMATCH; return; } if (location != oskar_mem_location(l) || location != oskar_mem_location(m)) { *status = OSKAR_ERR_LOCATION_MISMATCH; return; } if ((int)oskar_mem_length(l) < num_points || (int)oskar_mem_length(m) < num_points) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } oskar_mem_ensure(out, num_points, status); if (*status) return; if (location == OSKAR_CPU) { switch (oskar_mem_type(out)) { case OSKAR_SINGLE_COMPLEX: gaussian_circular_complex_f(num_points, oskar_mem_float_const(l, status), oskar_mem_float_const(m, status), inv_2_var_f, oskar_mem_float2(out, status)); break; case OSKAR_DOUBLE_COMPLEX: gaussian_circular_complex_d(num_points, oskar_mem_double_const(l, status), oskar_mem_double_const(m, status), inv_2_var, oskar_mem_double2(out, status)); break; case OSKAR_SINGLE_COMPLEX_MATRIX: gaussian_circular_matrix_f(num_points, oskar_mem_float_const(l, status), oskar_mem_float_const(m, status), inv_2_var_f, oskar_mem_float4c(out, status)); break; case OSKAR_DOUBLE_COMPLEX_MATRIX: gaussian_circular_matrix_d(num_points, oskar_mem_double_const(l, status), oskar_mem_double_const(m, status), inv_2_var, oskar_mem_double4c(out, status)); break; default: *status = OSKAR_ERR_BAD_DATA_TYPE; break; } } else { size_t local_size[] = {256, 1, 1}, global_size[] = {1, 1, 1}; const char* k = 0; const int is_dbl = oskar_mem_is_double(out); switch (oskar_mem_type(out)) { case OSKAR_SINGLE_COMPLEX: k = "gaussian_circular_complex_float"; break; case OSKAR_DOUBLE_COMPLEX: k = "gaussian_circular_complex_double"; break; case OSKAR_SINGLE_COMPLEX_MATRIX: k = "gaussian_circular_matrix_float"; break; case OSKAR_DOUBLE_COMPLEX_MATRIX: k = "gaussian_circular_matrix_double"; break; default: *status = OSKAR_ERR_BAD_DATA_TYPE; return; } oskar_device_check_local_size(location, 0, local_size); global_size[0] = oskar_device_global_size( (size_t) num_points, local_size[0]); const oskar_Arg args[] = { {INT_SZ, &num_points}, {PTR_SZ, oskar_mem_buffer_const(l)}, {PTR_SZ, oskar_mem_buffer_const(m)}, {is_dbl ? DBL_SZ : FLT_SZ, is_dbl ? (const void*)&inv_2_var : (const void*)&inv_2_var_f}, {PTR_SZ, oskar_mem_buffer(out)} }; oskar_device_launch_kernel(k, location, 1, local_size, global_size, sizeof(args) / sizeof(oskar_Arg), args, 0, 0, status); } }
void oskar_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_imager_update_plane_dft(oskar_Imager* h, size_t num_vis, const oskar_Mem* uu, const oskar_Mem* vv, const oskar_Mem* ww, const oskar_Mem* amps, const oskar_Mem* weight, oskar_Mem* plane, double* plane_norm, int* status) { size_t i, num_pixels; oskar_Thread** threads = 0; ThreadArgs* args = 0; if (*status) return; /* Check the image plane. */ num_pixels = (size_t) h->image_size; num_pixels *= num_pixels; if (oskar_mem_precision(plane) != h->imager_prec) *status = OSKAR_ERR_TYPE_MISMATCH; if (oskar_mem_is_complex(plane) || oskar_mem_is_matrix(plane)) *status = OSKAR_ERR_BAD_DATA_TYPE; oskar_mem_ensure(plane, num_pixels, status); if (*status) return; /* Set up worker threads. */ const size_t num_threads = (size_t) (h->num_devices); threads = (oskar_Thread**) calloc(num_threads, sizeof(oskar_Thread*)); args = (ThreadArgs*) calloc(num_threads, sizeof(ThreadArgs)); for (i = 0; i < num_threads; ++i) { args[i].h = h; args[i].thread_id = (int) i; args[i].num_vis = (int) num_vis; args[i].uu = uu; args[i].vv = vv; args[i].ww = ww; args[i].amp = amps; args[i].weight = weight; args[i].plane = plane; } /* Set status code. */ h->status = *status; /* Start the worker threads. */ h->i_block = 0; for (i = 0; i < num_threads; ++i) threads[i] = oskar_thread_create(run_blocks, (void*)&args[i], 0); /* Wait for worker threads to finish. */ for (i = 0; i < num_threads; ++i) { oskar_thread_join(threads[i]); oskar_thread_free(threads[i]); } free(threads); free(args); /* Get status code. */ *status = h->status; /* Update normalisation. */ if (oskar_mem_precision(weight) == OSKAR_DOUBLE) { const double* w = oskar_mem_double_const(weight, status); for (i = 0; i < num_vis; ++i) *plane_norm += w[i]; } else { const float* w = oskar_mem_float_const(weight, status); for (i = 0; i < num_vis; ++i) *plane_norm += w[i]; } }
void oskar_convert_brightness_to_jy(oskar_Mem* data, double beam_area_pixels, double pixel_area_sr, double frequency_hz, double min_peak_fraction, double min_abs_val, const char* reported_map_units, const char* default_map_units, int override_input_units, int* status) { static const double k_B = 1.3806488e-23; /* Boltzmann constant. */ double lambda, peak = 0.0, peak_min = 0.0, scaling = 1.0, val = 0.0; const char* unit_str = 0; int i = 0, num_pixels, units = 0, type; if (*status) return; /* Filter and find peak of image. */ num_pixels = (int) oskar_mem_length(data); type = oskar_mem_precision(data); if (type == OSKAR_SINGLE) { float *img = oskar_mem_float(data, status); for (i = 0; i < num_pixels; ++i) { val = img[i]; if (val > peak) peak = val; } peak_min = peak * min_peak_fraction; for (i = 0; i < num_pixels; ++i) { val = img[i]; if (val < peak_min || val < min_abs_val) img[i] = 0.0; } } else { double *img = oskar_mem_double(data, status); for (i = 0; i < num_pixels; ++i) { val = img[i]; if (val > peak) peak = val; } peak_min = peak * min_peak_fraction; for (i = 0; i < num_pixels; ++i) { val = img[i]; if (val < peak_min || val < min_abs_val) img[i] = 0.0; } } /* Find brightness units. */ unit_str = (!reported_map_units || override_input_units) ? default_map_units : reported_map_units; if (!strncmp(unit_str, "JY/BEAM", 7) || !strncmp(unit_str, "Jy/beam", 7)) units = JY_BEAM; else if (!strncmp(unit_str, "JY/PIXEL", 8) || !strncmp(unit_str, "Jy/pixel", 8)) units = JY_PIXEL; else if (!strncmp(unit_str, "mK", 2)) units = MK; else if (!strncmp(unit_str, "K", 1)) units = K; else *status = OSKAR_ERR_BAD_UNITS; /* Check if we need to convert the pixel values. */ if (units == JY_BEAM) { if (beam_area_pixels == 0.0) { oskar_log_error("Need beam area for maps in Jy/beam."); *status = OSKAR_ERR_BAD_UNITS; } else scaling = 1.0 / beam_area_pixels; } else if (units == K || units == MK) { if (units == MK) scaling = 1e-3; /* Convert milli-Kelvin to Kelvin. */ /* Convert temperature to Jansky per pixel. */ /* Brightness temperature to flux density conversion: * http://www.iram.fr/IRAMFR/IS/IS2002/html_1/node187.html */ /* Multiply by 2.0 * k_B * pixel_area * 10^26 / lambda^2. */ lambda = 299792458.0 / frequency_hz; scaling *= (2.0 * k_B * pixel_area_sr * 1e26 / (lambda*lambda)); } /* Scale pixels into Jy. */ if (scaling != 1.0) oskar_mem_scale_real(data, scaling, 0, oskar_mem_length(data), status); }
void oskar_imager_update_plane_wproj(oskar_Imager* h, size_t num_vis, const oskar_Mem* uu, const oskar_Mem* vv, const oskar_Mem* ww, const oskar_Mem* amps, const oskar_Mem* weight, oskar_Mem* plane, double* plane_norm, size_t* num_skipped, int* status) { int grid_size; size_t num_cells; if (*status) return; grid_size = oskar_imager_plane_size(h); num_cells = grid_size * grid_size; if (oskar_mem_precision(plane) != h->imager_prec) *status = OSKAR_ERR_TYPE_MISMATCH; if (oskar_mem_length(plane) < num_cells) oskar_mem_realloc(plane, num_cells, status); if (*status) return; if (h->imager_prec == OSKAR_DOUBLE) oskar_grid_wproj_d(h->num_w_planes, oskar_mem_int_const(h->w_support, status), h->oversample, h->conv_size_half, oskar_mem_double_const(h->w_kernels, status), num_vis, oskar_mem_double_const(uu, status), oskar_mem_double_const(vv, status), oskar_mem_double_const(ww, status), oskar_mem_double_const(amps, status), oskar_mem_double_const(weight, status), h->cellsize_rad, h->w_scale, grid_size, num_skipped, plane_norm, oskar_mem_double(plane, status)); else { char *fname = 0; #if SAVE_INPUT_DAT || SAVE_OUTPUT_DAT || SAVE_GRID fname = (char*) calloc(20 + h->input_root ? strlen(h->input_root) : 0, 1); #endif #if SAVE_INPUT_DAT { const float cellsize_rad_tmp = (const float) (h->cellsize_rad); const float w_scale_tmp = (const float) (h->w_scale); const size_t num_w_planes = (size_t) (h->num_w_planes); FILE* f; sprintf(fname, "%s_INPUT.dat", h->input_root); f = fopen(fname, "wb"); fwrite(&num_w_planes, sizeof(size_t), 1, f); fwrite(oskar_mem_void_const(h->w_support), sizeof(int), num_w_planes, f); fwrite(&h->oversample, sizeof(int), 1, f); fwrite(&h->conv_size_half, sizeof(int), 1, f); fwrite(oskar_mem_void_const(h->w_kernels), 2 * sizeof(float), h->num_w_planes * h->conv_size_half * h->conv_size_half, f); fwrite(&num_vis, sizeof(size_t), 1, f); fwrite(oskar_mem_void_const(uu), sizeof(float), num_vis, f); fwrite(oskar_mem_void_const(vv), sizeof(float), num_vis, f); fwrite(oskar_mem_void_const(ww), sizeof(float), num_vis, f); fwrite(oskar_mem_void_const(amps), 2 * sizeof(float), num_vis, f); fwrite(oskar_mem_void_const(weight), sizeof(float), num_vis, f); fwrite(&cellsize_rad_tmp, sizeof(float), 1, f); fwrite(&w_scale_tmp, sizeof(float), 1, f); fwrite(&grid_size, sizeof(int), 1, f); fclose(f); } #endif oskar_grid_wproj_f(h->num_w_planes, oskar_mem_int_const(h->w_support, status), h->oversample, h->conv_size_half, oskar_mem_float_const(h->w_kernels, status), num_vis, oskar_mem_float_const(uu, status), oskar_mem_float_const(vv, status), oskar_mem_float_const(ww, status), oskar_mem_float_const(amps, status), oskar_mem_float_const(weight, status), (float) (h->cellsize_rad), (float) (h->w_scale), grid_size, num_skipped, plane_norm, oskar_mem_float(plane, status)); #if SAVE_OUTPUT_DAT { FILE* f; sprintf(fname, "%s_OUTPUT.dat", h->input_root); f = fopen(fname, "wb"); fwrite(num_skipped, sizeof(size_t), 1, f); fwrite(plane_norm, sizeof(double), 1, f); fwrite(&grid_size, sizeof(int), 1, f); fwrite(oskar_mem_void_const(plane), 2 * sizeof(float), num_cells, f); fclose(f); } #endif #if SAVE_GRID sprintf(fname, "%s_GRID", h->input_root); oskar_mem_write_fits_cube(plane, fname, grid_size, grid_size, 1, 0, status); #endif free(fname); } }
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); }
static void load_coords(oskar_Mem* lon, oskar_Mem* lat, const char* filename, int* status) { int type = 0; FILE* file; char* line = 0; size_t n = 0, bufsize = 0; if (*status) return; /* Set initial size of coordinate arrays. */ type = oskar_mem_precision(lon); oskar_mem_realloc(lon, 100, status); oskar_mem_realloc(lat, 100, status); /* Open the file. */ file = fopen(filename, "r"); if (!file) { *status = OSKAR_ERR_FILE_IO; return; } /* Loop over lines in file. */ while (oskar_getline(&line, &bufsize, file) != OSKAR_ERR_EOF) { /* Set defaults. */ /* Longitude, latitude. */ double par[] = {0., 0.}; size_t num_param = sizeof(par) / sizeof(double); size_t num_required = 2, num_read = 0; /* Load coordinates. */ num_read = oskar_string_to_array_d(line, num_param, par); if (num_read < num_required) continue; /* Ensure enough space in arrays. */ if (oskar_mem_length(lon) <= n) { oskar_mem_realloc(lon, n + 100, status); oskar_mem_realloc(lat, n + 100, status); if (*status) break; } /* Store the coordinates. */ if (type == OSKAR_DOUBLE) { oskar_mem_double(lon, status)[n] = par[0] * M_PI/180.0; oskar_mem_double(lat, status)[n] = par[1] * M_PI/180.0; } else { oskar_mem_float(lon, status)[n] = par[0] * M_PI/180.0; oskar_mem_float(lat, status)[n] = par[1] * M_PI/180.0; } ++n; } /* Resize output arrays to final size. */ oskar_mem_realloc(lon, n, status); oskar_mem_realloc(lat, n, status); fclose(file); free(line); }
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); } }
TEST(imager, grid_sum) { int status = 0, type = OSKAR_DOUBLE; int size = 2048, grid_size = size * size; // Create and set up the imager. oskar_Imager* im = oskar_imager_create(type, &status); oskar_imager_set_grid_kernel(im, "pillbox", 1, 1, &status); oskar_imager_set_fov(im, 5.0); oskar_imager_set_size(im, size, &status); oskar_Mem* grid = oskar_mem_create(type | OSKAR_COMPLEX, OSKAR_CPU, grid_size, &status); ASSERT_EQ(0, status); // Create visibility data. int num_vis = 10000; oskar_Mem* uu = oskar_mem_create(type, OSKAR_CPU, num_vis, &status); oskar_Mem* vv = oskar_mem_create(type, OSKAR_CPU, num_vis, &status); oskar_Mem* ww = oskar_mem_create(type, OSKAR_CPU, num_vis, &status); oskar_Mem* vis = oskar_mem_create(type | OSKAR_COMPLEX, OSKAR_CPU, num_vis, &status); oskar_Mem* weight = oskar_mem_create(type, OSKAR_CPU, num_vis, &status); oskar_mem_random_gaussian(uu, 0, 1, 2, 3, 100.0, &status); oskar_mem_random_gaussian(vv, 4, 5, 6, 7, 100.0, &status); oskar_mem_set_value_real(vis, 1.0, 0, num_vis, &status); oskar_mem_set_value_real(weight, 1.0, 0, num_vis, &status); // Grid visibility data. double plane_norm = 0.0; oskar_imager_update_plane(im, num_vis, uu, vv, ww, vis, weight, grid, &plane_norm, 0, &status); ASSERT_DOUBLE_EQ((double)num_vis, plane_norm); // Sum the grid. double2* t = oskar_mem_double2(grid, &status); double sum = 0.0; for (int i = 0; i < grid_size; i++) sum += t[i].x; ASSERT_DOUBLE_EQ((double)num_vis, sum); // Finalise the image. oskar_imager_finalise_plane(im, grid, plane_norm, &status); ASSERT_EQ(0, status); #ifdef WRITE_FITS // Get the real part only. if (oskar_mem_precision(grid) == OSKAR_DOUBLE) { double *t = oskar_mem_double(grid, &status); for (int j = 0; j < grid_size; ++j) t[j] = t[2 * j]; } else { float *t = oskar_mem_float(grid, &status); for (int j = 0; j < grid_size; ++j) t[j] = t[2 * j]; } // Save the real part. fitsfile* f; long naxes[2] = {size, size}, firstpix[2] = {1, 1}; fits_create_file(&f, "test_imager_grid_sum.fits", &status); fits_create_img(f, (type == OSKAR_DOUBLE ? DOUBLE_IMG : FLOAT_IMG), 2, naxes, &status); fits_write_pix(f, (type == OSKAR_DOUBLE ? TDOUBLE : TFLOAT), firstpix, grid_size, oskar_mem_void(grid), &status); fits_close_file(f, &status); #endif // Clean up. oskar_imager_free(im, &status); oskar_mem_free(uu, &status); oskar_mem_free(vv, &status); oskar_mem_free(ww, &status); oskar_mem_free(vis, &status); oskar_mem_free(weight, &status); oskar_mem_free(grid, &status); }
void oskar_vis_block_write_ms(const oskar_VisBlock* blk, const oskar_VisHeader* header, oskar_MeasurementSet* ms, int* status) { const oskar_Mem *in_acorr, *in_xcorr, *in_uu, *in_vv, *in_ww; oskar_Mem *temp_vis = 0, *temp_uu = 0, *temp_vv = 0, *temp_ww = 0; double exposure_sec, interval_sec, t_start_mjd, t_start_sec; double ra_rad, dec_rad, ref_freq_hz; unsigned int a1, a2, num_baseln_in, num_baseln_out, num_channels; unsigned int num_pols_in, num_pols_out, num_stations, num_times, b, c, t; unsigned int i, i_out, prec, start_time_index, start_chan_index; unsigned int have_autocorr, have_crosscorr; const void *xcorr, *acorr; void* out; /* Check if safe to proceed. */ if (*status) return; /* Pull data from visibility structures. */ num_pols_out = oskar_ms_num_pols(ms); num_pols_in = oskar_vis_block_num_pols(blk); num_stations = oskar_vis_block_num_stations(blk); num_baseln_in = oskar_vis_block_num_baselines(blk); num_channels = oskar_vis_block_num_channels(blk); num_times = oskar_vis_block_num_times(blk); in_acorr = oskar_vis_block_auto_correlations_const(blk); in_xcorr = oskar_vis_block_cross_correlations_const(blk); in_uu = oskar_vis_block_baseline_uu_metres_const(blk); in_vv = oskar_vis_block_baseline_vv_metres_const(blk); in_ww = oskar_vis_block_baseline_ww_metres_const(blk); have_autocorr = oskar_vis_block_has_auto_correlations(blk); have_crosscorr = oskar_vis_block_has_cross_correlations(blk); start_time_index = oskar_vis_block_start_time_index(blk); start_chan_index = oskar_vis_block_start_channel_index(blk); ra_rad = oskar_vis_header_phase_centre_ra_deg(header) * D2R; dec_rad = oskar_vis_header_phase_centre_dec_deg(header) * D2R; exposure_sec = oskar_vis_header_time_average_sec(header); interval_sec = oskar_vis_header_time_inc_sec(header); t_start_mjd = oskar_vis_header_time_start_mjd_utc(header); ref_freq_hz = oskar_vis_header_freq_start_hz(header); prec = oskar_mem_precision(in_xcorr); t_start_sec = t_start_mjd * 86400.0 + interval_sec * (start_time_index + 0.5); /* Check that there is something to write. */ if (!have_autocorr && !have_crosscorr) return; /* Get number of output baselines. */ num_baseln_out = num_baseln_in; if (have_autocorr) num_baseln_out += num_stations; /* Check polarisation dimension consistency: * num_pols_in can be less than num_pols_out, but not vice-versa. */ if (num_pols_in > num_pols_out) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } /* Check the dimensions match. */ if (oskar_ms_num_pols(ms) != num_pols_out || oskar_ms_num_stations(ms) != num_stations) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } /* Check the reference frequencies match. */ if (fabs(oskar_ms_ref_freq_hz(ms) - ref_freq_hz) > 1e-10) { *status = OSKAR_ERR_VALUE_MISMATCH; return; } /* Check the phase centres are the same. */ if (fabs(oskar_ms_phase_centre_ra_rad(ms) - ra_rad) > 1e-10 || fabs(oskar_ms_phase_centre_dec_rad(ms) - dec_rad) > 1e-10) { *status = OSKAR_ERR_VALUE_MISMATCH; return; } /* Add visibilities and u,v,w coordinates. */ temp_vis = oskar_mem_create(prec | OSKAR_COMPLEX, OSKAR_CPU, num_baseln_out * num_channels * num_pols_out, status); temp_uu = oskar_mem_create(prec, OSKAR_CPU, num_baseln_out, status); temp_vv = oskar_mem_create(prec, OSKAR_CPU, num_baseln_out, status); temp_ww = oskar_mem_create(prec, OSKAR_CPU, num_baseln_out, status); xcorr = oskar_mem_void_const(in_xcorr); acorr = oskar_mem_void_const(in_acorr); out = oskar_mem_void(temp_vis); if (prec == OSKAR_DOUBLE) { const double *uu_in, *vv_in, *ww_in; double *uu_out, *vv_out, *ww_out; uu_in = oskar_mem_double_const(in_uu, status); vv_in = oskar_mem_double_const(in_vv, status); ww_in = oskar_mem_double_const(in_ww, status); uu_out = oskar_mem_double(temp_uu, status); vv_out = oskar_mem_double(temp_vv, status); ww_out = oskar_mem_double(temp_ww, status); for (t = 0; t < num_times; ++t) { /* Construct the baseline coordinates for the given time. */ int start_row = (start_time_index + t) * num_baseln_out; for (a1 = 0, b = 0, i_out = 0; a1 < num_stations; ++a1) { if (have_autocorr) { uu_out[i_out] = 0.0; vv_out[i_out] = 0.0; ww_out[i_out] = 0.0; ++i_out; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++a2, ++b, ++i_out) { i = num_baseln_in * t + b; uu_out[i_out] = uu_in[i]; vv_out[i_out] = vv_in[i]; ww_out[i_out] = ww_in[i]; } } } for (c = 0, i_out = 0; c < num_channels; ++c) { /* Construct amplitude data for the given time and channel. */ if (num_pols_in == 4) { for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; ((double4c*)out)[i_out++] = ((const double4c*)acorr)[i]; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; ((double4c*)out)[i_out++] = ((const double4c*)xcorr)[i]; } } } } else if (num_pols_in == 1 && num_pols_out == 1) { for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; ((double2*)out)[i_out++] = ((const double2*)acorr)[i]; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; ((double2*)out)[i_out++] = ((const double2*)xcorr)[i]; } } } } else { double2 vis_amp, *out_; out_ = (double2*)out; for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; vis_amp = ((const double2*)acorr)[i]; out_[i_out + 0] = vis_amp; /* XX */ out_[i_out + 1].x = 0.0; /* XY */ out_[i_out + 1].y = 0.0; /* XY */ out_[i_out + 2].x = 0.0; /* YX */ out_[i_out + 2].y = 0.0; /* YX */ out_[i_out + 3] = vis_amp; /* YY */ i_out += 4; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; vis_amp = ((const double2*)xcorr)[i]; out_[i_out + 0] = vis_amp; /* XX */ out_[i_out + 1].x = 0.0; /* XY */ out_[i_out + 1].y = 0.0; /* XY */ out_[i_out + 2].x = 0.0; /* YX */ out_[i_out + 2].y = 0.0; /* YX */ out_[i_out + 3] = vis_amp; /* YY */ i_out += 4; } } } } } oskar_ms_write_coords_d(ms, start_row, num_baseln_out, uu_out, vv_out, ww_out, exposure_sec, interval_sec, t_start_sec + (t * interval_sec)); oskar_ms_write_vis_d(ms, start_row, start_chan_index, num_channels, num_baseln_out, (const double*)out); } } else if (prec == OSKAR_SINGLE) { const float *uu_in, *vv_in, *ww_in; float *uu_out, *vv_out, *ww_out; uu_in = oskar_mem_float_const(in_uu, status); vv_in = oskar_mem_float_const(in_vv, status); ww_in = oskar_mem_float_const(in_ww, status); uu_out = oskar_mem_float(temp_uu, status); vv_out = oskar_mem_float(temp_vv, status); ww_out = oskar_mem_float(temp_ww, status); for (t = 0; t < num_times; ++t) { /* Construct the baseline coordinates for the given time. */ int start_row = (start_time_index + t) * num_baseln_out; for (a1 = 0, b = 0, i_out = 0; a1 < num_stations; ++a1) { if (have_autocorr) { uu_out[i_out] = 0.0; vv_out[i_out] = 0.0; ww_out[i_out] = 0.0; ++i_out; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++a2, ++b, ++i_out) { i = num_baseln_in * t + b; uu_out[i_out] = uu_in[i]; vv_out[i_out] = vv_in[i]; ww_out[i_out] = ww_in[i]; } } } for (c = 0, i_out = 0; c < num_channels; ++c) { /* Construct amplitude data for the given time and channel. */ if (num_pols_in == 4) { for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; ((float4c*)out)[i_out++] = ((const float4c*)acorr)[i]; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; ((float4c*)out)[i_out++] = ((const float4c*)xcorr)[i]; } } } } else if (num_pols_in == 1 && num_pols_out == 1) { for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; ((float2*)out)[i_out++] = ((const float2*)acorr)[i]; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; ((float2*)out)[i_out++] = ((const float2*)xcorr)[i]; } } } } else { float2 vis_amp, *out_; out_ = (float2*)out; for (a1 = 0, b = 0; a1 < num_stations; ++a1) { if (have_autocorr) { i = num_stations * (t * num_channels + c) + a1; vis_amp = ((const float2*)acorr)[i]; out_[i_out + 0] = vis_amp; /* XX */ out_[i_out + 1].x = 0.0; /* XY */ out_[i_out + 1].y = 0.0; /* XY */ out_[i_out + 2].x = 0.0; /* YX */ out_[i_out + 2].y = 0.0; /* YX */ out_[i_out + 3] = vis_amp; /* YY */ i_out += 4; } if (have_crosscorr) { for (a2 = a1 + 1; a2 < num_stations; ++b, ++a2) { i = num_baseln_in * (t * num_channels + c) + b; vis_amp = ((const float2*)xcorr)[i]; out_[i_out + 0] = vis_amp; /* XX */ out_[i_out + 1].x = 0.0; /* XY */ out_[i_out + 1].y = 0.0; /* XY */ out_[i_out + 2].x = 0.0; /* YX */ out_[i_out + 2].y = 0.0; /* YX */ out_[i_out + 3] = vis_amp; /* YY */ i_out += 4; } } } } } oskar_ms_write_coords_f(ms, start_row, num_baseln_out, uu_out, vv_out, ww_out, exposure_sec, interval_sec, t_start_sec + (t * interval_sec)); oskar_ms_write_vis_f(ms, start_row, start_chan_index, num_channels, num_baseln_out, (const float*)out); } } else { *status = OSKAR_ERR_BAD_DATA_TYPE; } /* Cleanup. */ oskar_mem_free(temp_vis, status); oskar_mem_free(temp_uu, status); oskar_mem_free(temp_vv, status); oskar_mem_free(temp_ww, status); }
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_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_); } } } }
oskar_Sky* oskar_sky_from_image(int precision, const oskar_Mem* image, int image_width, int image_height, double image_ra_deg, double image_dec_deg, double image_cellsize_deg, double image_freq_hz, double spectral_index, int* status) { int i, type, x, y; double crval[2], crpix[2], cdelt[2], val; oskar_Sky* sky; /* Check if safe to proceed. */ if (*status) return 0; /* Check the image size is even. */ if ((image_width % 2) || (image_height % 2)) { *status = OSKAR_ERR_INVALID_ARGUMENT; return 0; } /* Get reference pixels and reference values in radians. */ crpix[0] = image_width / 2 + 1; crpix[1] = image_height / 2 + 1; crval[0] = image_ra_deg * M_PI / 180.0; crval[1] = image_dec_deg * M_PI / 180.0; /* Compute sine of pixel deltas for inverse orthographic projection. */ cdelt[0] = -sin(image_cellsize_deg * M_PI / 180.0); cdelt[1] = -cdelt[0]; /* Create a sky model. */ sky = oskar_sky_create(precision, OSKAR_CPU, 0, status); /* Store the image pixels. */ type = oskar_mem_precision(image); if (type == OSKAR_SINGLE) { const float *img = oskar_mem_float_const(image, status); for (y = 0, i = 0; y < image_height; ++y) { for (x = 0; x < image_width; ++x) { /* Check pixel value. */ val = (double) (img[image_width * y + x]); if (val == 0.0) continue; set_pixel(sky, i++, x, y, val, crval, crpix, cdelt, image_freq_hz, spectral_index, status); } } } else { const double *img = oskar_mem_double_const(image, status); for (y = 0, i = 0; y < image_height; ++y) { for (x = 0; x < image_width; ++x) { /* Check pixel value. */ val = img[image_width * y + x]; if (val == 0.0) continue; set_pixel(sky, i++, x, y, val, crval, crpix, cdelt, image_freq_hz, spectral_index, status); } } } /* Return the sky model. */ oskar_sky_resize(sky, i, status); return sky; }
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); }