oskar_VisBlock* oskar_simulator_finalise_block(oskar_Simulator* h, int block_index, int* status) { int i, i_active; oskar_VisBlock *b0 = 0, *b = 0; if (*status) return 0; /* The visibilities must be copied back * at the end of the block simulation. */ /* Combine all vis blocks into the first one. */ i_active = (block_index + 1) % 2; b0 = h->d[0].vis_block_cpu[!i_active]; if (!h->coords_only) { oskar_Mem *xc0 = 0, *ac0 = 0; xc0 = oskar_vis_block_cross_correlations(b0); ac0 = oskar_vis_block_auto_correlations(b0); for (i = 1; i < h->num_devices; ++i) { b = h->d[i].vis_block_cpu[!i_active]; if (oskar_vis_block_has_cross_correlations(b)) oskar_mem_add(xc0, xc0, oskar_vis_block_cross_correlations(b), oskar_mem_length(xc0), status); if (oskar_vis_block_has_auto_correlations(b)) oskar_mem_add(ac0, ac0, oskar_vis_block_auto_correlations(b), oskar_mem_length(ac0), status); } } /* Calculate baseline uvw coordinates for the block. */ if (oskar_vis_block_has_cross_correlations(b0)) { const oskar_Mem *x, *y, *z; x = oskar_telescope_station_measured_x_offset_ecef_metres_const(h->tel); y = oskar_telescope_station_measured_y_offset_ecef_metres_const(h->tel); z = oskar_telescope_station_measured_z_offset_ecef_metres_const(h->tel); oskar_convert_ecef_to_baseline_uvw( oskar_telescope_num_stations(h->tel), x, y, z, oskar_telescope_phase_centre_ra_rad(h->tel), oskar_telescope_phase_centre_dec_rad(h->tel), oskar_vis_block_num_times(b0), oskar_vis_header_time_start_mjd_utc(h->header), oskar_vis_header_time_inc_sec(h->header) / 86400.0, oskar_vis_block_start_time_index(b0), oskar_vis_block_baseline_uu_metres(b0), oskar_vis_block_baseline_vv_metres(b0), oskar_vis_block_baseline_ww_metres(b0), h->temp, status); } /* Add uncorrelated system noise to the combined visibilities. */ if (!h->coords_only) { oskar_vis_block_add_system_noise(b0, h->header, h->tel, block_index, h->temp, status); } /* Return a pointer to the block. */ return b0; }
void oskar_beam_pattern_set_telescope_model(oskar_BeamPattern* h, const oskar_Telescope* model, int* status) { if (*status) return; /* Check the model is not empty. */ if (oskar_telescope_num_stations(model) == 0) { oskar_log_error(h->log, "Telescope model is empty."); *status = OSKAR_ERR_SETTINGS_TELESCOPE; return; } /* Remove any existing telescope model, and copy the new one. */ oskar_telescope_free(h->tel, status); h->tel = oskar_telescope_create_copy(model, OSKAR_CPU, status); h->pol_mode = oskar_telescope_pol_mode(h->tel); h->phase_centre_deg[0] = oskar_telescope_phase_centre_ra_rad(h->tel) * 180.0 / M_PI; h->phase_centre_deg[1] = oskar_telescope_phase_centre_dec_rad(h->tel) * 180.0 / M_PI; /* Analyse the telescope model. */ oskar_telescope_analyse(h->tel, status); if (h->log) oskar_telescope_log_summary(h->tel, h->log, status); }
void oskar_simulator_check_init(oskar_Simulator* h, int* status) { if (*status) return; /* Check that the telescope model has been set. */ if (!h->tel) { oskar_log_error(h->log, "Telescope model not set."); *status = OSKAR_ERR_SETTINGS_TELESCOPE; return; } /* Create the visibility header if required. */ if (!h->header) set_up_vis_header(h, status); /* Calculate source parameters if required. */ if (!h->init_sky) { int i, num_failed = 0; double ra0, dec0; /* Compute source direction cosines relative to phase centre. */ ra0 = oskar_telescope_phase_centre_ra_rad(h->tel); dec0 = oskar_telescope_phase_centre_dec_rad(h->tel); for (i = 0; i < h->num_sky_chunks; ++i) { oskar_sky_evaluate_relative_directions(h->sky_chunks[i], ra0, dec0, status); /* Evaluate extended source parameters. */ oskar_sky_evaluate_gaussian_source_parameters(h->sky_chunks[i], h->zero_failed_gaussians, ra0, dec0, &num_failed, status); } if (num_failed > 0) { if (h->zero_failed_gaussians) oskar_log_warning(h->log, "Gaussian ellipse solution failed " "for %i sources. These will have their fluxes " "set to zero.", num_failed); else oskar_log_warning(h->log, "Gaussian ellipse solution failed " "for %i sources. These will be simulated " "as point sources.", num_failed); } h->init_sky = 1; } /* Check that each compute device has been set up. */ set_up_device_data(h, status); }
static void sim_baselines(oskar_Simulator* h, DeviceData* d, oskar_Sky* sky, int channel_index_block, int time_index_block, int time_index_simulation, int* status) { int num_baselines, num_stations, num_src, num_times_block, num_channels; double dt_dump_days, t_start, t_dump, gast, frequency, ra0, dec0; const oskar_Mem *x, *y, *z; oskar_Mem* alias = 0; /* Get dimensions. */ num_baselines = oskar_telescope_num_baselines(d->tel); num_stations = oskar_telescope_num_stations(d->tel); num_src = oskar_sky_num_sources(sky); num_times_block = oskar_vis_block_num_times(d->vis_block); num_channels = oskar_vis_block_num_channels(d->vis_block); /* Return if there are no sources in the chunk, * or if block time index requested is outside the valid range. */ if (num_src == 0 || time_index_block >= num_times_block) return; /* Get the time and frequency of the visibility slice being simulated. */ dt_dump_days = h->time_inc_sec / 86400.0; t_start = h->time_start_mjd_utc; t_dump = t_start + dt_dump_days * (time_index_simulation + 0.5); gast = oskar_convert_mjd_to_gast_fast(t_dump); frequency = h->freq_start_hz + channel_index_block * h->freq_inc_hz; /* Scale source fluxes with spectral index and rotation measure. */ oskar_sky_scale_flux_with_frequency(sky, frequency, status); /* Evaluate station u,v,w coordinates. */ ra0 = oskar_telescope_phase_centre_ra_rad(d->tel); dec0 = oskar_telescope_phase_centre_dec_rad(d->tel); x = oskar_telescope_station_true_x_offset_ecef_metres_const(d->tel); y = oskar_telescope_station_true_y_offset_ecef_metres_const(d->tel); z = oskar_telescope_station_true_z_offset_ecef_metres_const(d->tel); oskar_convert_ecef_to_station_uvw(num_stations, x, y, z, ra0, dec0, gast, d->u, d->v, d->w, status); /* Set dimensions of Jones matrices. */ if (d->R) oskar_jones_set_size(d->R, num_stations, num_src, status); if (d->Z) oskar_jones_set_size(d->Z, num_stations, num_src, status); oskar_jones_set_size(d->J, num_stations, num_src, status); oskar_jones_set_size(d->E, num_stations, num_src, status); oskar_jones_set_size(d->K, num_stations, num_src, status); /* Evaluate station beam (Jones E: may be matrix). */ oskar_timer_resume(d->tmr_E); oskar_evaluate_jones_E(d->E, num_src, OSKAR_RELATIVE_DIRECTIONS, oskar_sky_l(sky), oskar_sky_m(sky), oskar_sky_n(sky), d->tel, gast, frequency, d->station_work, time_index_simulation, status); oskar_timer_pause(d->tmr_E); #if 0 /* Evaluate ionospheric phase (Jones Z: scalar) and join with Jones E. * NOTE this is currently only a CPU implementation. */ if (d->Z) { oskar_evaluate_jones_Z(d->Z, num_src, sky, d->tel, &settings->ionosphere, gast, frequency, &(d->workJonesZ), status); oskar_timer_resume(d->tmr_join); oskar_jones_join(d->E, d->Z, d->E, status); oskar_timer_pause(d->tmr_join); } #endif /* Evaluate parallactic angle (Jones R: matrix), and join with Jones Z*E. * TODO Move this into station beam evaluation instead. */ if (d->R) { oskar_timer_resume(d->tmr_E); oskar_evaluate_jones_R(d->R, num_src, oskar_sky_ra_rad_const(sky), oskar_sky_dec_rad_const(sky), d->tel, gast, status); oskar_timer_pause(d->tmr_E); oskar_timer_resume(d->tmr_join); oskar_jones_join(d->R, d->E, d->R, status); oskar_timer_pause(d->tmr_join); } /* Evaluate interferometer phase (Jones K: scalar). */ oskar_timer_resume(d->tmr_K); oskar_evaluate_jones_K(d->K, num_src, oskar_sky_l_const(sky), oskar_sky_m_const(sky), oskar_sky_n_const(sky), d->u, d->v, d->w, frequency, oskar_sky_I_const(sky), h->source_min_jy, h->source_max_jy, status); oskar_timer_pause(d->tmr_K); /* Join Jones K with Jones Z*E. */ oskar_timer_resume(d->tmr_join); oskar_jones_join(d->J, d->K, d->R ? d->R : d->E, status); oskar_timer_pause(d->tmr_join); /* Create alias for auto/cross-correlations. */ oskar_timer_resume(d->tmr_correlate); alias = oskar_mem_create_alias(0, 0, 0, status); /* Auto-correlate for this time and channel. */ if (oskar_vis_block_has_auto_correlations(d->vis_block)) { oskar_mem_set_alias(alias, oskar_vis_block_auto_correlations(d->vis_block), num_stations * (num_channels * time_index_block + channel_index_block), num_stations, status); oskar_auto_correlate(alias, num_src, d->J, sky, status); } /* Cross-correlate for this time and channel. */ if (oskar_vis_block_has_cross_correlations(d->vis_block)) { oskar_mem_set_alias(alias, oskar_vis_block_cross_correlations(d->vis_block), num_baselines * (num_channels * time_index_block + channel_index_block), num_baselines, status); oskar_cross_correlate(alias, num_src, d->J, sky, d->tel, d->u, d->v, d->w, gast, frequency, status); } /* Free alias for auto/cross-correlations. */ oskar_mem_free(alias, status); oskar_timer_pause(d->tmr_correlate); }
static void set_up_vis_header(oskar_Simulator* h, int* status) { int num_stations, vis_type; const double rad2deg = 180.0/M_PI; int write_autocorr = 0, write_crosscorr = 0; if (*status) return; /* Check type of correlations to produce. */ if (h->correlation_type == 'C') write_crosscorr = 1; else if (h->correlation_type == 'A') write_autocorr = 1; else if (h->correlation_type == 'B') { write_autocorr = 1; write_crosscorr = 1; } /* Create visibility header. */ num_stations = oskar_telescope_num_stations(h->tel); vis_type = h->prec | OSKAR_COMPLEX; if (oskar_telescope_pol_mode(h->tel) == OSKAR_POL_MODE_FULL) vis_type |= OSKAR_MATRIX; h->header = oskar_vis_header_create(vis_type, h->prec, h->max_times_per_block, h->num_time_steps, h->num_channels, h->num_channels, num_stations, write_autocorr, write_crosscorr, status); /* Add metadata from settings. */ oskar_vis_header_set_freq_start_hz(h->header, h->freq_start_hz); oskar_vis_header_set_freq_inc_hz(h->header, h->freq_inc_hz); oskar_vis_header_set_time_start_mjd_utc(h->header, h->time_start_mjd_utc); oskar_vis_header_set_time_inc_sec(h->header, h->time_inc_sec); /* Add settings file contents if defined. */ if (h->settings_path) { oskar_Mem* temp; temp = oskar_mem_read_binary_raw(h->settings_path, OSKAR_CHAR, OSKAR_CPU, status); oskar_mem_copy(oskar_vis_header_settings(h->header), temp, status); oskar_mem_free(temp, status); } /* Copy other metadata from telescope model. */ oskar_vis_header_set_time_average_sec(h->header, oskar_telescope_time_average_sec(h->tel)); oskar_vis_header_set_channel_bandwidth_hz(h->header, oskar_telescope_channel_bandwidth_hz(h->tel)); oskar_vis_header_set_phase_centre(h->header, 0, oskar_telescope_phase_centre_ra_rad(h->tel) * rad2deg, oskar_telescope_phase_centre_dec_rad(h->tel) * rad2deg); oskar_vis_header_set_telescope_centre(h->header, oskar_telescope_lon_rad(h->tel) * rad2deg, oskar_telescope_lat_rad(h->tel) * rad2deg, oskar_telescope_alt_metres(h->tel)); oskar_mem_copy(oskar_vis_header_station_x_offset_ecef_metres(h->header), oskar_telescope_station_true_x_offset_ecef_metres_const(h->tel), status); oskar_mem_copy(oskar_vis_header_station_y_offset_ecef_metres(h->header), oskar_telescope_station_true_y_offset_ecef_metres_const(h->tel), status); oskar_mem_copy(oskar_vis_header_station_z_offset_ecef_metres(h->header), oskar_telescope_station_true_z_offset_ecef_metres_const(h->tel), status); }
void oskar_beam_pattern_generate_coordinates(oskar_BeamPattern* h, int beam_coord_type, int* status) { size_t num_pixels = 0; int nside = 0; /* Check if safe to proceed. */ if (*status) return; /* If memory is already allocated, do nothing. */ if (h->x) return; /* Calculate number of pixels if possible. */ if (h->coord_grid_type == 'B') /* Beam image */ { num_pixels = h->width * h->height; } else if (h->coord_grid_type == 'H') /* Healpix */ { nside = h->nside; num_pixels = 12 * nside * nside; } else if (h->coord_grid_type == 'S') /* Sky model */ num_pixels = 0; else { *status = OSKAR_ERR_INVALID_ARGUMENT; return; } /* Create output arrays. */ h->x = oskar_mem_create(h->prec, OSKAR_CPU, num_pixels, status); h->y = oskar_mem_create(h->prec, OSKAR_CPU, num_pixels, status); h->z = oskar_mem_create(h->prec, OSKAR_CPU, num_pixels, status); /* Get equatorial or horizon coordinates. */ if (h->coord_frame_type == 'E') { /* * Equatorial coordinates. */ switch (h->coord_grid_type) { case 'B': /* Beam image */ { oskar_evaluate_image_lmn_grid(h->width, h->height, h->fov_deg[0]*(M_PI/180.0), h->fov_deg[1]*(M_PI/180.0), 1, h->x, h->y, h->z, status); break; } case 'H': /* Healpix */ { int num_points, type, i; double ra0 = 0.0, dec0 = 0.0; oskar_Mem *theta, *phi; /* Generate theta and phi from nside. */ num_points = 12 * nside * nside; type = oskar_mem_type(h->x); theta = oskar_mem_create(type, OSKAR_CPU, num_points, status); phi = oskar_mem_create(type, OSKAR_CPU, num_points, status); oskar_convert_healpix_ring_to_theta_phi(nside, theta, phi, status); /* Convert theta from polar angle to elevation. */ if (type == OSKAR_DOUBLE) { double* theta_ = oskar_mem_double(theta, status); for (i = 0; i < num_points; ++i) theta_[i] = 90.0 - theta_[i]; } else if (type == OSKAR_SINGLE) { float* theta_ = oskar_mem_float(theta, status); for (i = 0; i < num_points; ++i) theta_[i] = 90.0f - theta_[i]; } else { *status = OSKAR_ERR_BAD_DATA_TYPE; } /* Evaluate beam phase centre coordinates in equatorial frame. */ if (beam_coord_type == OSKAR_SPHERICAL_TYPE_EQUATORIAL) { ra0 = oskar_telescope_phase_centre_ra_rad(h->tel); dec0 = oskar_telescope_phase_centre_dec_rad(h->tel); } else if (beam_coord_type == OSKAR_SPHERICAL_TYPE_AZEL) { /* TODO convert from az0, el0 to ra0, dec0 */ *status = OSKAR_FAIL; } else { *status = OSKAR_ERR_INVALID_ARGUMENT; } /* Convert equatorial angles to direction cosines in the frame * of the beam phase centre. */ oskar_convert_lon_lat_to_relative_directions(num_points, phi, theta, ra0, dec0, h->x, h->y, h->z, status); /* Free memory. */ oskar_mem_free(theta, status); oskar_mem_free(phi, status); break; } case 'S': /* Sky model */ { oskar_Mem *ra, *dec; int type = 0, num_points = 0; type = oskar_mem_type(h->x); ra = oskar_mem_create(type, OSKAR_CPU, 0, status); dec = oskar_mem_create(type, OSKAR_CPU, 0, status); load_coords(ra, dec, h->sky_model_file, status); num_points = oskar_mem_length(ra); oskar_mem_realloc(h->x, num_points, status); oskar_mem_realloc(h->y, num_points, status); oskar_mem_realloc(h->z, num_points, status); oskar_convert_lon_lat_to_relative_directions( num_points, ra, dec, oskar_telescope_phase_centre_ra_rad(h->tel), oskar_telescope_phase_centre_dec_rad(h->tel), h->x, h->y, h->z, status); oskar_mem_free(ra, status); oskar_mem_free(dec, status); break; } default: *status = OSKAR_ERR_INVALID_ARGUMENT; break; }; /* Set the return values. */ h->coord_type = OSKAR_RELATIVE_DIRECTIONS; h->lon0 = oskar_telescope_phase_centre_ra_rad(h->tel); h->lat0 = oskar_telescope_phase_centre_dec_rad(h->tel); } else if (h->coord_frame_type == 'H') { /* * Horizon coordinates. */ switch (h->coord_grid_type) { case 'B': /* Beam image */ { /* NOTE: This is for an all-sky image centred on the zenith. */ oskar_evaluate_image_lmn_grid(h->width, h->height, M_PI, M_PI, 1, h->x, h->y, h->z, status); break; } case 'H': /* Healpix */ { int num_points, type; oskar_Mem *theta, *phi; num_points = 12 * nside * nside; type = oskar_mem_type(h->x); theta = oskar_mem_create(type, OSKAR_CPU, num_points, status); phi = oskar_mem_create(type, OSKAR_CPU, num_points, status); oskar_convert_healpix_ring_to_theta_phi(nside, theta, phi, status); oskar_convert_theta_phi_to_enu_directions(num_points, theta, phi, h->x, h->y, h->z, status); oskar_mem_free(theta, status); oskar_mem_free(phi, status); break; } default: *status = OSKAR_ERR_INVALID_ARGUMENT; break; }; /* Set the return values. */ h->coord_type = OSKAR_ENU_DIRECTIONS; h->lon0 = 0.0; h->lat0 = M_PI / 2.0; } else { *status = OSKAR_ERR_INVALID_ARGUMENT; } /* Set the number of pixels. */ h->num_pixels = oskar_mem_length(h->x); }