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); }
int main(int argc, char** argv) { // ===== Declare options ================================================== oskar::OptionParser opt("oskar_vis_to_ascii_table", oskar_version_string()); opt.set_description("Converts an OSKAR visibility binary file to an ASCII " "table format with the following columns:\n " "[1] index, [2] baseline-uu, [3] baseline-vv, [4] baseline-ww " "[5] Real, [6] Imag. " "The table is written out in baseline-time order where baseline " "is the fastest varying dimension"); opt.add_required("OSKAR vis file"); opt.add_optional("output file name"); opt.add_flag("-c", "Channel index to write to file. (default = 0)", 1, "0", false, "--channel"); opt.add_flag("-p", "Polarisation ID to write to file. (default = 0) " "(0=I, 1=Q, 2=U, 3=V, 4=XX, 5=XY, 6=YX, 7=YY)", 1, "0", false, "--polarisation"); opt.add_flag("-t", "Time index to write to file. (default = all)", 1, "", false, "--time"); opt.add_flag("-w", "Output baseline coordinates in wavelengths. " "(default = metres)", false, "--baseline_wavelengths"); opt.add_flag("-h", "Write a summary header in the ASCII table. "); opt.add_flag("-v", "Verbose mode."); opt.add_flag("--csv", "Write in CSV format"); opt.add_flag("-s", "Write output table to standard output instead of to file.", false, "--stdout"); if (!opt.check_options(argc, argv)) return EXIT_FAILURE; // ===== Read options ==================================================== const char* vis_file = opt.get_arg(0); std::string txt_file; if (opt.num_args() == 2) txt_file = std::string(opt.get_arg(1)); else { txt_file = std::string(vis_file) + ".txt"; } int c = 0, p = 0, t = -1; if (opt.is_set("-c")) c = opt.get_int("-c"); if (opt.is_set("-p")) p = opt.get_int("-p"); if (opt.is_set("-t")) t = opt.get_int("-t"); bool metres = !opt.is_set("-w"); bool write_header = opt.is_set("-h"); bool csv = opt.is_set("--csv"); bool verbose = opt.is_set("-v"); // ===== Write table ====================================================== int status = 0; oskar_Binary* h = oskar_binary_create(vis_file, 'r', &status); oskar_Vis* vis = oskar_vis_read(h, &status); if (status) { fprintf(stderr, "ERROR: Unable to read specified visibility file: %s\n", vis_file); oskar_vis_free(vis, &status); oskar_binary_free(h); return status; } oskar_binary_free(h); int num_chan = oskar_vis_num_channels(vis); int num_times = oskar_vis_num_times(vis); int num_baselines = oskar_vis_num_baselines(vis); int num_pol = oskar_vis_num_pols(vis); int num_stations = oskar_vis_num_stations(vis); int total_vis = num_chan * num_times * num_baselines * num_pol; double freq_start_hz = oskar_vis_freq_start_hz(vis); double freq_inc_hz = oskar_vis_freq_inc_hz(vis); double freq_hz = freq_start_hz + c * freq_inc_hz; double lambda_m = 299792458.0 / freq_hz; if (t != -1 && t > num_times-1) { fprintf(stderr, "ERROR: Time index out of range.\n"); return EXIT_FAILURE; } if (c > num_chan-1) { fprintf(stderr, "ERROR: Channel index out of range.\n"); return EXIT_FAILURE; } FILE* out; if (!opt.is_set("-s")) { out = fopen(txt_file.c_str(), "w"); if (out == NULL) return EXIT_FAILURE; } else { out = stdout; } const oskar_Mem* uu = oskar_vis_baseline_uu_metres_const(vis); const oskar_Mem* vv = oskar_vis_baseline_vv_metres_const(vis); const oskar_Mem* ww = oskar_vis_baseline_ww_metres_const(vis); const oskar_Mem* amp = oskar_vis_amplitude_const(vis); // amplitudes dims: channel x times x baselines x pol int amp_offset = c * num_times * num_baselines; if (t != -1) amp_offset += t * num_baselines; // baseline dims: times x baselines int baseline_offset = 0; if (t != -1) baseline_offset = t * num_baselines; int type = oskar_mem_type(uu); int num_vis_out = num_baselines; if (t == -1) num_vis_out *= num_times; if (verbose) { write_header_(stdout, total_vis, num_chan, num_times, num_baselines, num_pol, num_stations, num_vis_out, c, freq_hz, lambda_m, p, t, metres); #if 0 fprintf(stdout, "amp_offset = %i\n", amp_offset); fprintf(stdout, "baseline_offset = %i\n", baseline_offset); #endif } // Write header if specified if (write_header) { write_header_(out, total_vis, num_chan, num_times, num_baselines, num_pol, num_stations, num_vis_out, c, freq_hz, lambda_m, p, t, metres); char pre = '#'; fprintf(out, "%c\n", pre); fprintf(out, "%c %s %-14s %-15s %-15s %-23s %-15s\n", pre, "Idx", " uu", " vv", " ww", " Amp. Re.", " Amp. Im."); } if (type == OSKAR_DOUBLE) { const double* uu_ = oskar_mem_double_const(uu, &status); const double* vv_ = oskar_mem_double_const(vv, &status); const double* ww_ = oskar_mem_double_const(ww, &status); const double4c* amp_ = oskar_mem_double4c_const(amp, &status); int aIdx = amp_offset; int bIdx = baseline_offset; for (int i = 0; i < num_vis_out; ++i, ++bIdx, ++aIdx) { double2 a = getPolAmp_<double2, double4c>(amp_[aIdx], p); double buu = (metres)? uu_[bIdx] : uu_[bIdx]/lambda_m; double bvv = (metres)? vv_[bIdx] : vv_[bIdx]/lambda_m; double bww = (metres)? ww_[bIdx] : ww_[bIdx]/lambda_m; writeData_<double, double2>(i, buu, bvv, bww, a, csv, out); } } else // OSKAR_SINGLE { const float* uu_ = oskar_mem_float_const(uu, &status); const float* vv_ = oskar_mem_float_const(vv, &status); const float* ww_ = oskar_mem_float_const(ww, &status); const float4c* amp_ = oskar_mem_float4c_const(amp, &status); int aIdx = amp_offset; int bIdx = baseline_offset; for (int i = 0; i < num_vis_out; ++i, ++bIdx, ++aIdx) { float2 a = getPolAmp_<float2, float4c>(amp_[aIdx], p); float buu = (metres)? uu_[bIdx] : uu_[bIdx]/lambda_m; float bvv = (metres)? vv_[bIdx] : vv_[bIdx]/lambda_m; float bww = (metres)? ww_[bIdx] : ww_[bIdx]/lambda_m; writeData_<float, float2>(i, buu, bvv, bww, a, csv, out); } } fclose(out); oskar_vis_free(vis, &status); return 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; } }