/* Evaluate the TEC value for each pierce point - note: at the moment this is * just the accumulation of one or more TID screens. * TODO convert this to a stand-alone function. */ static void oskar_evaluate_TEC(oskar_WorkJonesZ* work, int num_pp, const oskar_SettingsIonosphere* settings, double gast, int* status) { int i; /* FIXME(BM) For now limit number of screens to 1, this can be removed * if a TEC model which is valid for multiple screens is implemented */ if (settings->num_TID_screens > 1) *status = OSKAR_ERR_INVALID_ARGUMENT; oskar_mem_set_value_real(work->total_TEC, 0.0, 0, 0, status); /* Loop over TID screens to evaluate TEC values */ for (i = 0; i < settings->num_TID_screens; ++i) { oskar_mem_set_value_real(work->screen_TEC, 0.0, 0, 0, status); /* Evaluate TEC values for the screen */ oskar_evaluate_tec_tid(work->screen_TEC, num_pp, work->pp_lon, work->pp_lat, work->pp_rel_path, settings->TEC0, &settings->TID[i], gast); /* Accumulate into total TEC */ /* FIXME(BM) addition is not physical for more than one TEC screen in * the way TIDs are currently evaluated as TEC0 is added into both * screens. */ oskar_mem_add(work->total_TEC, work->total_TEC, work->screen_TEC, oskar_mem_length(work->total_TEC), status); } }
void oskar_sky_set_gaussian_parameters(oskar_Sky* sky, double FWHM_major, double FWHM_minor, double position_angle, int* status) { /* Check if safe to proceed. */ if (*status) return; oskar_mem_set_value_real(sky->fwhm_major_rad, FWHM_major, 0, 0, status); oskar_mem_set_value_real(sky->fwhm_minor_rad, FWHM_minor, 0, 0, status); oskar_mem_set_value_real(sky->pa_rad, position_angle, 0, 0, status); }
TEST(element_weights_errors, test_evaluate) { int num_elements = 10000; double element_gain = 1.0; double element_gain_error = 0.0; double element_phase = 0.0 * M_PI; double element_phase_error = 0.0 * M_PI; int error = 0; unsigned int seed = 1; oskar_Mem *d_gain, *d_gain_error, *d_phase, *d_phase_error, *d_errors; d_gain = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &error); d_gain_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &error); d_phase = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &error); d_phase_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &error); d_errors = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU, num_elements, &error); ASSERT_EQ(0, error) << oskar_get_error_string(error); oskar_mem_set_value_real(d_gain, element_gain, 0, 0, &error); oskar_mem_set_value_real(d_gain_error, element_gain_error, 0, 0, &error); oskar_mem_set_value_real(d_phase, element_phase, 0, 0, &error); oskar_mem_set_value_real(d_phase_error, element_phase_error, 0, 0, &error); oskar_mem_set_value_real(d_errors, 0.0, 0, 0, &error); ASSERT_EQ(0, error) << oskar_get_error_string(error); // Evaluate weights errors. oskar_evaluate_element_weights_errors(num_elements, d_gain, d_gain_error, d_phase, d_phase_error, seed, 0, 0, d_errors, &error); ASSERT_EQ(0, error) << oskar_get_error_string(error); // Write memory to file for inspection. const char* fname = "temp_test_element_errors.dat"; FILE* file = fopen(fname, "w"); oskar_mem_save_ascii(file, 5, num_elements, &error, d_gain, d_gain_error, d_phase, d_phase_error, d_errors); fclose(file); remove(fname); // Free memory. oskar_mem_free(d_gain, &error); oskar_mem_free(d_gain_error, &error); oskar_mem_free(d_phase, &error); oskar_mem_free(d_phase_error, &error); oskar_mem_free(d_errors, &error); ASSERT_EQ(0, error) << oskar_get_error_string(error); }
void oskar_station_resize(oskar_Station* station, int num_elements, int* status) { /* Check if safe to proceed. */ if (*status) return; /* Resize arrays in the model. */ oskar_mem_realloc(station->element_true_x_enu_metres, num_elements, status); oskar_mem_realloc(station->element_true_y_enu_metres, num_elements, status); oskar_mem_realloc(station->element_true_z_enu_metres, num_elements, status); oskar_mem_realloc(station->element_measured_x_enu_metres, num_elements, status); oskar_mem_realloc(station->element_measured_y_enu_metres, num_elements, status); oskar_mem_realloc(station->element_measured_z_enu_metres, num_elements, status); oskar_mem_realloc(station->element_weight, num_elements, status); oskar_mem_realloc(station->element_gain, num_elements, status); oskar_mem_realloc(station->element_gain_error, num_elements, status); oskar_mem_realloc(station->element_phase_offset_rad, num_elements, status); oskar_mem_realloc(station->element_phase_error_rad, num_elements, status); oskar_mem_realloc(station->element_x_alpha_cpu, num_elements, status); oskar_mem_realloc(station->element_x_beta_cpu, num_elements, status); oskar_mem_realloc(station->element_x_gamma_cpu, num_elements, status); oskar_mem_realloc(station->element_y_alpha_cpu, num_elements, status); oskar_mem_realloc(station->element_y_beta_cpu, num_elements, status); oskar_mem_realloc(station->element_y_gamma_cpu, num_elements, status); oskar_mem_realloc(station->element_types, num_elements, status); oskar_mem_realloc(station->element_types_cpu, num_elements, status); oskar_mem_realloc(station->element_mount_types_cpu, num_elements, status); /* Initialise any new elements with default values. */ if (num_elements > station->num_elements) { int offset, num_new; offset = station->num_elements; num_new = num_elements - offset; /* Must set default element weight, gain and orientation. */ oskar_mem_set_value_real(station->element_gain, 1.0, offset, num_new, status); oskar_mem_set_value_real(station->element_weight, 1.0, offset, num_new, status); memset(oskar_mem_char(station->element_mount_types_cpu) + offset, 'F', num_new); } /* Set the new number of elements. */ station->num_elements = num_elements; }
void oskar_station_override_element_time_variable_phases(oskar_Station* s, double phase_std, int* status) { int i; /* Check if safe to proceed. */ if (*status) return; /* Check if there are child stations. */ if (oskar_station_has_child(s)) { /* Recursive call to find the last level (i.e. the element data). */ for (i = 0; i < s->num_elements; ++i) { oskar_station_override_element_time_variable_phases( oskar_station_child(s, i), phase_std, status); } } else { /* Override element data at last level. */ oskar_mem_set_value_real(s->element_phase_error_rad, phase_std, 0, 0, status); } }
TEST(Mem, set_value_real_double_complex_matrix) { // Double precision complex matrix. int n = 100, status = 0; oskar_Mem *mem, *mem2; mem = oskar_mem_create(OSKAR_DOUBLE_COMPLEX_MATRIX, OSKAR_GPU, n, &status); oskar_mem_set_value_real(mem, 6.5, 0, 0, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); mem2 = oskar_mem_create_copy(mem, OSKAR_CPU, &status); double4c* v = oskar_mem_double4c(mem2, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); for (int i = 0; i < n; ++i) { EXPECT_DOUBLE_EQ(v[i].a.x, 6.5); EXPECT_DOUBLE_EQ(v[i].a.y, 0.0); EXPECT_DOUBLE_EQ(v[i].b.x, 0.0); EXPECT_DOUBLE_EQ(v[i].b.y, 0.0); EXPECT_DOUBLE_EQ(v[i].c.x, 0.0); EXPECT_DOUBLE_EQ(v[i].c.y, 0.0); EXPECT_DOUBLE_EQ(v[i].d.x, 6.5); EXPECT_DOUBLE_EQ(v[i].d.y, 0.0); } oskar_mem_free(mem, &status); oskar_mem_free(mem2, &status); }
static void evaluate_station_beam_enu_directions(oskar_Mem* beam_pattern, int np, const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z, const oskar_Station* station, oskar_StationWork* work, int time_index, double frequency_hz, double GAST, int* status) { if (*status) return; switch (oskar_station_type(station)) { case OSKAR_STATION_TYPE_AA: { oskar_evaluate_station_beam_aperture_array(beam_pattern, station, np, x, y, z, GAST, frequency_hz, work, time_index, status); break; } case OSKAR_STATION_TYPE_ISOTROPIC: { oskar_mem_set_value_real(beam_pattern, 1.0, 0, np, status); break; } case OSKAR_STATION_TYPE_GAUSSIAN_BEAM: { oskar_Mem *l, *m, *n; /* Relative direction cosines */ double fwhm, f0; l = oskar_station_work_enu_direction_x(work); m = oskar_station_work_enu_direction_y(work); n = oskar_station_work_enu_direction_z(work); compute_relative_directions(l, m, n, np, x, y, z, station, GAST, status); fwhm = oskar_station_gaussian_beam_fwhm_rad(station); f0 =oskar_station_gaussian_beam_reference_freq_hz(station); fwhm *= f0 / frequency_hz; oskar_evaluate_station_beam_gaussian(beam_pattern, np, l, m, z, fwhm, status); break; } case OSKAR_STATION_TYPE_VLA_PBCOR: { oskar_Mem *l, *m, *n; /* Relative direction cosines */ l = oskar_station_work_enu_direction_x(work); m = oskar_station_work_enu_direction_y(work); n = oskar_station_work_enu_direction_z(work); compute_relative_directions(l, m, n, np, x, y, z, station, GAST, status); oskar_evaluate_vla_beam_pbcor(beam_pattern, np, l, m, frequency_hz, status); break; } default: { *status = OSKAR_ERR_SETTINGS_TELESCOPE; break; } }; }
TEST(Mem, set_value_real_single) { // Single precision real. int n = 100, status = 0; oskar_Mem *mem; mem = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU, n, &status); oskar_mem_set_value_real(mem, 4.5, 0, 0, &status); float* v = oskar_mem_float(mem, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); for (int i = 0; i < n; ++i) { EXPECT_FLOAT_EQ(v[i], 4.5); } oskar_mem_free(mem, &status); }
TEST(Mem, set_value_real_double) { // Double precision real. int n = 100, status = 0; oskar_Mem *mem; mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, n, &status); oskar_mem_set_value_real(mem, 4.5, 0, 0, &status); double* v = oskar_mem_double(mem, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); for (int i = 0; i < n; ++i) { EXPECT_DOUBLE_EQ(v[i], 4.5); } oskar_mem_free(mem, &status); }
TEST(Mem, set_value_real_single_complex) { // Single precision complex. int n = 100, status = 0; oskar_Mem *mem, *mem2; mem = oskar_mem_create(OSKAR_SINGLE_COMPLEX, OSKAR_GPU, n, &status); oskar_mem_set_value_real(mem, 6.5, 0, 0, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); mem2 = oskar_mem_create_copy(mem, OSKAR_CPU, &status); float2* v = oskar_mem_float2(mem2, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); for (int i = 0; i < n; ++i) { EXPECT_FLOAT_EQ(v[i].x, 6.5); EXPECT_FLOAT_EQ(v[i].y, 0.0); } oskar_mem_free(mem, &status); oskar_mem_free(mem2, &status); }
TEST(element_weights_errors, test_reinit) { int num_elements = 5; int status = 0; double gain = 1.5; double gain_error = 0.2; double phase = 0.1 * M_PI; double phase_error = (5 / 180.0) * M_PI; oskar_Mem *d_errors, *d_gain, *d_gain_error, *d_phase, *d_phase_error; d_errors = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU, num_elements, &status); d_gain = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &status); d_gain_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &status); d_phase = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &status); d_phase_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); oskar_mem_set_value_real(d_gain, gain, 0, 0, &status); oskar_mem_set_value_real(d_gain_error, gain_error, 0, 0, &status); oskar_mem_set_value_real(d_phase, phase, 0, 0, &status); oskar_mem_set_value_real(d_phase_error, phase_error, 0, 0, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); int num_channels = 2; int num_chunks = 3; int num_stations = 5; int num_times = 3; unsigned int seed = 1; const char* fname = "temp_test_weights_error_reinit.dat"; FILE* file = fopen(fname, "w"); for (int chan = 0; chan < num_channels; ++chan) { fprintf(file, "channel: %i\n", chan); for (int chunk = 0; chunk < num_chunks; ++chunk) { fprintf(file, " chunk: %i\n", chunk); ASSERT_EQ(0, status) << oskar_get_error_string(status); for (int t = 0; t < num_times; ++t) { fprintf(file, " time: %i\n", t); for (int s = 0; s < num_stations; ++s) { fprintf(file, " station: %i ==> ", s); oskar_evaluate_element_weights_errors(num_elements, d_gain, d_gain_error, d_phase, d_phase_error, seed, t, s, d_errors, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); oskar_Mem *h_errors = oskar_mem_create_copy(d_errors, OSKAR_CPU, &status); double2* errors = oskar_mem_double2(h_errors, &status); for (int i = 0; i < num_elements; ++i) { fprintf(file, "(% -6.4f, % -6.4f), ", errors[i].x, errors[i].y); } fprintf(file, "\n"); oskar_mem_free(h_errors, &status); } } ASSERT_EQ(0, status) << oskar_get_error_string(status); } } fclose(file); // remove(fname); oskar_mem_free(d_gain, &status); oskar_mem_free(d_gain_error, &status); oskar_mem_free(d_phase, &status); oskar_mem_free(d_phase_error, &status); oskar_mem_free(d_errors, &status); }
TEST(element_weights_errors, test_apply) { int num_elements = 10000; int status = 0; double gain = 1.5; double gain_error = 0.2; double phase = 0.1 * M_PI; double phase_error = (5 / 180.0) * M_PI; double weight_gain = 1.0; double weight_phase = 0.5 * M_PI; double2 weight; weight.x = weight_gain * cos(weight_phase); weight.y = weight_gain * sin(weight_phase); oskar_Mem *d_gain, *d_gain_error, *d_phase, *d_phase_error, *d_errors; oskar_Mem *h_weights, *d_weights; d_errors = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU, num_elements, &status); d_gain = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &status); d_gain_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &status); d_phase = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &status); d_phase_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, num_elements, &status); h_weights = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU, num_elements, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); oskar_mem_set_value_real(d_gain, gain, 0, 0, &status); oskar_mem_set_value_real(d_gain_error, gain_error, 0, 0, &status); oskar_mem_set_value_real(d_phase, phase, 0, 0, &status); oskar_mem_set_value_real(d_phase_error, phase_error, 0, 0, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); double2* h_weights_ = oskar_mem_double2(h_weights, &status); for (int i = 0; i < num_elements; ++i) { h_weights_[i].x = weight.x; h_weights_[i].y = weight.y; } d_weights = oskar_mem_create_copy(h_weights, OSKAR_GPU, &status); oskar_evaluate_element_weights_errors(num_elements, d_gain, d_gain_error, d_phase, d_phase_error, 0, 0, 0, d_errors, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); oskar_mem_element_multiply(NULL, d_weights, d_errors, num_elements, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); // Write memory to file for inspection. const char* fname = "temp_test_weights.dat"; FILE* file = fopen(fname, "w"); oskar_mem_save_ascii(file, 7, num_elements, &status, d_gain, d_gain_error, d_phase, d_phase_error, d_errors, h_weights, d_weights); fclose(file); remove(fname); // Free memory. oskar_mem_free(d_gain, &status); oskar_mem_free(d_gain_error, &status); oskar_mem_free(d_phase, &status); oskar_mem_free(d_phase_error, &status); oskar_mem_free(d_errors, &status); oskar_mem_free(h_weights, &status); oskar_mem_free(d_weights, &status); ASSERT_EQ(0, status) << oskar_get_error_string(status); }
void oskar_element_evaluate( const oskar_Element* model, double orientation_x, double orientation_y, int offset_points, int num_points, const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z, double frequency_hz, oskar_Mem* theta, oskar_Mem* phi, int offset_out, oskar_Mem* output, int* status) { double dipole_length_m; if (*status) return; if (!oskar_mem_is_complex(output)) { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } oskar_mem_ensure(output, offset_out + num_points, status); oskar_mem_ensure(theta, num_points, status); oskar_mem_ensure(phi, num_points, status); /* Get the element model properties. */ const int element_type = model->element_type; const int taper_type = model->taper_type; const int id = oskar_find_closest_match_d(frequency_hz, oskar_element_num_freq(model), oskar_element_freqs_hz_const(model)); dipole_length_m = model->dipole_length; if (model->dipole_length_units == OSKAR_WAVELENGTHS) dipole_length_m *= (C_0 / frequency_hz); /* Compute modified theta and phi coordinates for dipole X. */ oskar_convert_enu_directions_to_theta_phi(offset_points, num_points, x, y, z, (M_PI/2) - orientation_x, theta, phi, status); /* Check if element type is isotropic. */ if (element_type == OSKAR_ELEMENT_TYPE_ISOTROPIC) oskar_mem_set_value_real(output, 1.0, offset_out, num_points, status); /* Evaluate polarised response if output array is matrix type. */ if (oskar_mem_is_matrix(output)) { const int offset_out_real = offset_out * 8; const int offset_out_cplx = offset_out * 4; if (oskar_element_has_x_spherical_wave_data(model, id)) oskar_evaluate_spherical_wave_sum(num_points, theta, phi, model->x_lmax[id], model->x_te[id], model->x_tm[id], 4, offset_out_cplx + 0, output, status); else if (oskar_element_has_x_spline_data(model, id)) { oskar_splines_evaluate(model->x_h_re[id], num_points, theta, phi, 8, offset_out_real + 0, output, status); oskar_splines_evaluate(model->x_h_im[id], num_points, theta, phi, 8, offset_out_real + 1, output, status); oskar_splines_evaluate(model->x_v_re[id], num_points, theta, phi, 8, offset_out_real + 2, output, status); oskar_splines_evaluate(model->x_v_im[id], num_points, theta, phi, 8, offset_out_real + 3, output, status); oskar_convert_ludwig3_to_theta_phi_components(num_points, phi, 4, offset_out_cplx + 0, output, status); } else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE) oskar_evaluate_dipole_pattern(num_points, theta, phi, frequency_hz, dipole_length_m, 4, offset_out_cplx + 0, output, status); else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE) oskar_evaluate_geometric_dipole_pattern(num_points, theta, phi, 4, offset_out_cplx + 0, output, status); /* Compute modified theta and phi coordinates for dipole Y. */ oskar_convert_enu_directions_to_theta_phi(offset_points, num_points, x, y, z, (M_PI/2) - orientation_y, theta, phi, status); if (oskar_element_has_y_spherical_wave_data(model, id)) oskar_evaluate_spherical_wave_sum(num_points, theta, phi, model->y_lmax[id], model->y_te[id], model->y_tm[id], 4, offset_out_cplx + 2, output, status); else if (oskar_element_has_y_spline_data(model, id)) { oskar_splines_evaluate(model->y_h_re[id], num_points, theta, phi, 8, offset_out_real + 4, output, status); oskar_splines_evaluate(model->y_h_im[id], num_points, theta, phi, 8, offset_out_real + 5, output, status); oskar_splines_evaluate(model->y_v_re[id], num_points, theta, phi, 8, offset_out_real + 6, output, status); oskar_splines_evaluate(model->y_v_im[id], num_points, theta, phi, 8, offset_out_real + 7, output, status); oskar_convert_ludwig3_to_theta_phi_components(num_points, phi, 4, offset_out_cplx + 2, output, status); } else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE) oskar_evaluate_dipole_pattern(num_points, theta, phi, frequency_hz, dipole_length_m, 4, offset_out_cplx + 2, output, status); else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE) oskar_evaluate_geometric_dipole_pattern(num_points, theta, phi, 4, offset_out_cplx + 2, output, status); } else /* Scalar response. */ { const int offset_out_real = offset_out * 2; if (oskar_element_has_scalar_spline_data(model, id)) { oskar_splines_evaluate(model->scalar_re[id], num_points, theta, phi, 2, offset_out_real + 0, output, status); oskar_splines_evaluate(model->scalar_im[id], num_points, theta, phi, 2, offset_out_real + 1, output, status); } else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE) oskar_evaluate_dipole_pattern(num_points, theta, phi, frequency_hz, dipole_length_m, 1, offset_out, output, status); else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE) oskar_evaluate_geometric_dipole_pattern(num_points, theta, phi, 1, offset_out, output, status); } /* Apply element tapering, if specified. */ if (taper_type == OSKAR_ELEMENT_TAPER_COSINE) oskar_apply_element_taper_cosine(num_points, model->cosine_power, theta, offset_out, output, status); else if (taper_type == OSKAR_ELEMENT_TAPER_GAUSSIAN) oskar_apply_element_taper_gaussian(num_points, model->gaussian_fwhm_rad, theta, offset_out, output, status); }
void oskar_imager_read_coords_vis(oskar_Imager* h, const char* filename, int i_file, int num_files, int* percent_done, int* percent_next, int* status) { oskar_Binary* vis_file; oskar_VisHeader* header; oskar_Mem *uu, *vv, *ww, *weight, *time_centroid, *time_slice; int coord_prec, max_times_per_block, tags_per_block, i_block, num_blocks; int num_times_total, num_stations, num_baselines, num_pols; double time_start_mjd, time_inc_sec; if (*status) return; /* Read the header. */ vis_file = oskar_binary_create(filename, 'r', status); header = oskar_vis_header_read(vis_file, status); if (*status) { oskar_vis_header_free(header, status); oskar_binary_free(vis_file); return; } coord_prec = oskar_vis_header_coord_precision(header); max_times_per_block = oskar_vis_header_max_times_per_block(header); tags_per_block = oskar_vis_header_num_tags_per_block(header); num_times_total = oskar_vis_header_num_times_total(header); num_stations = oskar_vis_header_num_stations(header); num_baselines = num_stations * (num_stations - 1) / 2; num_pols = oskar_type_is_matrix(oskar_vis_header_amp_type(header)) ? 4 : 1; num_blocks = (num_times_total + max_times_per_block - 1) / max_times_per_block; time_start_mjd = oskar_vis_header_time_start_mjd_utc(header) * 86400.0; time_inc_sec = oskar_vis_header_time_inc_sec(header); /* Set visibility meta-data. */ oskar_imager_set_vis_frequency(h, oskar_vis_header_freq_start_hz(header), oskar_vis_header_freq_inc_hz(header), oskar_vis_header_num_channels_total(header)); oskar_imager_set_vis_phase_centre(h, oskar_vis_header_phase_centre_ra_deg(header), oskar_vis_header_phase_centre_dec_deg(header)); /* Create scratch arrays. Weights are all 1. */ uu = oskar_mem_create(coord_prec, OSKAR_CPU, 0, status); vv = oskar_mem_create(coord_prec, OSKAR_CPU, 0, status); ww = oskar_mem_create(coord_prec, OSKAR_CPU, 0, status); time_centroid = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, num_baselines * max_times_per_block, status); time_slice = oskar_mem_create_alias(0, 0, 0, status); weight = oskar_mem_create(h->imager_prec, OSKAR_CPU, num_baselines * num_pols * max_times_per_block, status); oskar_mem_set_value_real(weight, 1.0, 0, 0, status); /* Loop over visibility blocks. */ for (i_block = 0; i_block < num_blocks; ++i_block) { int t, num_times, num_channels, start_time, start_chan, end_chan; int dim_start_and_size[6]; size_t num_rows; if (*status) break; /* Read block metadata. */ oskar_timer_resume(h->tmr_read); oskar_binary_set_query_search_start(vis_file, i_block * tags_per_block, status); oskar_binary_read(vis_file, OSKAR_INT, OSKAR_TAG_GROUP_VIS_BLOCK, OSKAR_VIS_BLOCK_TAG_DIM_START_AND_SIZE, i_block, sizeof(dim_start_and_size), dim_start_and_size, status); start_time = dim_start_and_size[0]; start_chan = dim_start_and_size[1]; num_times = dim_start_and_size[2]; num_channels = dim_start_and_size[3]; num_rows = num_times * num_baselines; end_chan = start_chan + num_channels - 1; /* Fill in the time centroid values. */ for (t = 0; t < num_times; ++t) { oskar_mem_set_alias(time_slice, time_centroid, t * num_baselines, num_baselines, status); oskar_mem_set_value_real(time_slice, time_start_mjd + (start_time + t + 0.5) * time_inc_sec, 0, num_baselines, status); } /* Read the baseline coordinates. */ oskar_binary_read_mem(vis_file, uu, OSKAR_TAG_GROUP_VIS_BLOCK, OSKAR_VIS_BLOCK_TAG_BASELINE_UU, i_block, status); oskar_binary_read_mem(vis_file, vv, OSKAR_TAG_GROUP_VIS_BLOCK, OSKAR_VIS_BLOCK_TAG_BASELINE_VV, i_block, status); oskar_binary_read_mem(vis_file, ww, OSKAR_TAG_GROUP_VIS_BLOCK, OSKAR_VIS_BLOCK_TAG_BASELINE_WW, i_block, status); /* Update the imager with the data. */ oskar_timer_pause(h->tmr_read); oskar_imager_update(h, num_rows, start_chan, end_chan, num_pols, uu, vv, ww, 0, weight, time_centroid, status); *percent_done = (int) round(100.0 * ( (i_block + 1) / (double)(num_blocks * num_files) + i_file / (double)num_files)); if (h->log && percent_next && *percent_done >= *percent_next) { oskar_log_message(h->log, 'S', -2, "%3d%% ...", *percent_done); *percent_next = 10 + 10 * (*percent_done / 10); } } oskar_mem_free(uu, status); oskar_mem_free(vv, status); oskar_mem_free(ww, status); oskar_mem_free(weight, status); oskar_mem_free(time_centroid, status); oskar_mem_free(time_slice, status); oskar_vis_header_free(header, status); oskar_binary_free(vis_file); }
void oskar_element_evaluate(const oskar_Element* model, oskar_Mem* output, double orientation_x, double orientation_y, int num_points, const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z, double frequency_hz, oskar_Mem* theta, oskar_Mem* phi, int* status) { int element_type, taper_type, freq_id; double dipole_length_m; /* Check if safe to proceed. */ if (*status) return; /* Check that the output array is complex. */ if (!oskar_mem_is_complex(output)) { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } /* Resize output array if required. */ if ((int)oskar_mem_length(output) < num_points) oskar_mem_realloc(output, num_points, status); /* Get the element model properties. */ element_type = model->element_type; taper_type = model->taper_type; dipole_length_m = model->dipole_length; if (model->dipole_length_units == OSKAR_WAVELENGTHS) dipole_length_m *= (C_0 / frequency_hz); /* Check if element type is isotropic. */ if (element_type == OSKAR_ELEMENT_TYPE_ISOTROPIC) oskar_mem_set_value_real(output, 1.0, 0, 0, status); /* Ensure there is enough space in the theta and phi work arrays. */ if ((int)oskar_mem_length(theta) < num_points) oskar_mem_realloc(theta, num_points, status); if ((int)oskar_mem_length(phi) < num_points) oskar_mem_realloc(phi, num_points, status); /* Compute modified theta and phi coordinates for dipole X. */ oskar_convert_enu_directions_to_theta_phi(num_points, x, y, z, M_PI_2 - orientation_x, theta, phi, status); /* Evaluate polarised response if output array is matrix type. */ if (oskar_mem_is_matrix(output)) { /* Check if spline data present for dipole X. */ if (oskar_element_has_x_spline_data(model)) { /* Get the frequency index. */ freq_id = oskar_find_closest_match_d(frequency_hz, oskar_element_num_freq(model), oskar_element_freqs_hz_const(model)); /* Evaluate spline pattern for dipole X. */ oskar_splines_evaluate(output, 0, 8, model->x_h_re[freq_id], num_points, theta, phi, status); oskar_splines_evaluate(output, 1, 8, model->x_h_im[freq_id], num_points, theta, phi, status); oskar_splines_evaluate(output, 2, 8, model->x_v_re[freq_id], num_points, theta, phi, status); oskar_splines_evaluate(output, 3, 8, model->x_v_im[freq_id], num_points, theta, phi, status); /* Convert from Ludwig-3 to spherical representation. */ oskar_convert_ludwig3_to_theta_phi_components(output, 0, 4, num_points, phi, status); } else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE) { /* Evaluate dipole pattern for dipole X. */ oskar_evaluate_dipole_pattern(output, num_points, theta, phi, frequency_hz, dipole_length_m, 0, 4, status); } else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE) { /* Evaluate dipole pattern for dipole X. */ oskar_evaluate_geometric_dipole_pattern(output, num_points, theta, phi, 0, 4, status); } /* Compute modified theta and phi coordinates for dipole Y. */ oskar_convert_enu_directions_to_theta_phi(num_points, x, y, z, M_PI_2 - orientation_y, theta, phi, status); /* Check if spline data present for dipole Y. */ if (oskar_element_has_y_spline_data(model)) { /* Get the frequency index. */ freq_id = oskar_find_closest_match_d(frequency_hz, oskar_element_num_freq(model), oskar_element_freqs_hz_const(model)); /* Evaluate spline pattern for dipole Y. */ oskar_splines_evaluate(output, 4, 8, model->y_h_re[freq_id], num_points, theta, phi, status); oskar_splines_evaluate(output, 5, 8, model->y_h_im[freq_id], num_points, theta, phi, status); oskar_splines_evaluate(output, 6, 8, model->y_v_re[freq_id], num_points, theta, phi, status); oskar_splines_evaluate(output, 7, 8, model->y_v_im[freq_id], num_points, theta, phi, status); /* Convert from Ludwig-3 to spherical representation. */ oskar_convert_ludwig3_to_theta_phi_components(output, 2, 4, num_points, phi, status); } else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE) { /* Evaluate dipole pattern for dipole Y. */ oskar_evaluate_dipole_pattern(output, num_points, theta, phi, frequency_hz, dipole_length_m, 2, 4, status); } else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE) { /* Evaluate dipole pattern for dipole Y. */ oskar_evaluate_geometric_dipole_pattern(output, num_points, theta, phi, 2, 4, status); } } /* Scalar response. */ else { /* Check if scalar spline data present. */ if (oskar_element_has_scalar_spline_data(model)) { /* Get the frequency index. */ freq_id = oskar_find_closest_match_d(frequency_hz, oskar_element_num_freq(model), oskar_element_freqs_hz_const(model)); oskar_splines_evaluate(output, 0, 2, model->scalar_re[freq_id], num_points, theta, phi, status); oskar_splines_evaluate(output, 1, 2, model->scalar_im[freq_id], num_points, theta, phi, status); } else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE) { oskar_evaluate_dipole_pattern(output, num_points, theta, phi, frequency_hz, dipole_length_m, 0, 1, status); } else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE) { oskar_evaluate_geometric_dipole_pattern(output, num_points, theta, phi, 0, 1, status); } } /* Apply element tapering, if specified. */ if (taper_type == OSKAR_ELEMENT_TAPER_COSINE) { oskar_apply_element_taper_cosine(output, num_points, model->cosine_power, theta, status); } else if (taper_type == OSKAR_ELEMENT_TAPER_GAUSSIAN) { oskar_apply_element_taper_gaussian(output, num_points, model->gaussian_fwhm_rad, theta, 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_evaluate_tec_tid(oskar_Mem* tec, int num_directions, const oskar_Mem* lon, const oskar_Mem* lat, const oskar_Mem* rel_path_length, double TEC0, oskar_SettingsTIDscreen* TID, double gast) { int i, j, type; double pp_lon, pp_lat; double pp_sec; double pp_tec; double amp, w, th, v; /* TID parameters */ double time; double earth_radius = 6365.0; /* km -- FIXME */ int status = 0; /* TODO check types, dimensions etc of memory */ type = oskar_mem_type(tec); oskar_mem_set_value_real(tec, 0.0, 0, 0, &status); /* Loop over TIDs */ for (i = 0; i < TID->num_components; ++i) { amp = TID->amp[i]; /* convert from km to rads */ w = TID->wavelength[i] / (earth_radius + TID->height_km); th = TID->theta[i] * M_PI/180.; /* convert from km/h to rad/s */ v = (TID->speed[i]/(earth_radius + TID->height_km)) / 3600; time = gast * 86400.0; /* days->sec */ /* Loop over directions */ for (j = 0; j < num_directions; ++j) { if (type == OSKAR_DOUBLE) { pp_lon = oskar_mem_double_const(lon, &status)[j]; pp_lat = oskar_mem_double_const(lat, &status)[j]; pp_sec = oskar_mem_double_const(rel_path_length, &status)[j]; pp_tec = pp_sec * amp * TEC0 * ( cos( (2.0*M_PI/w) * (cos(th)*pp_lon - v*time) ) + cos( (2.0*M_PI/w) * (sin(th)*pp_lat - v*time) ) ); pp_tec += TEC0; oskar_mem_double(tec, &status)[j] += pp_tec; } else { pp_lon = (double)oskar_mem_float_const(lon, &status)[j]; pp_lat = (double)oskar_mem_float_const(lat, &status)[j]; pp_sec = (double)oskar_mem_float_const(rel_path_length, &status)[j]; pp_tec = pp_sec * amp * TEC0 * ( cos( (2.0*M_PI/w) * (cos(th)*pp_lon - v*time) ) + cos( (2.0*M_PI/w) * (sin(th)*pp_lat - v*time) ) ); pp_tec += TEC0; oskar_mem_float(tec, &status)[j] += (float)pp_tec; } } /* loop over directions */ } /* loop over components. */ }