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_telescope_log_summary(const oskar_Telescope* telescope, int* status) { if (*status) return; oskar_log_section('M', "Telescope model summary"); oskar_log_value('M', 0, "Longitude [deg]", "%.3f", oskar_telescope_lon_rad(telescope) * 180.0 / M_PI); oskar_log_value('M', 0, "Latitude [deg]", "%.3f", oskar_telescope_lat_rad(telescope) * 180.0 / M_PI); oskar_log_value('M', 0, "Altitude [m]", "%.0f", oskar_telescope_alt_metres(telescope)); oskar_log_value('M', 0, "Num. stations", "%d", oskar_telescope_num_stations(telescope)); oskar_log_value('M', 0, "Max station size", "%d", oskar_telescope_max_station_size(telescope)); oskar_log_value('M', 0, "Max station depth", "%d", oskar_telescope_max_station_depth(telescope)); oskar_log_value('M', 0, "Identical stations", "%s", oskar_telescope_identical_stations(telescope) ? "true" : "false"); }
void oskar_simulator_set_telescope_model(oskar_Simulator* 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); /* Analyse the telescope model. */ oskar_telescope_analyse(h->tel, status); if (h->log) oskar_telescope_log_summary(h->tel, h->log, 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_device_data(oskar_Simulator* h, int* status) { int i, dev_loc, complx, vistype, num_stations, num_src; if (*status) return; /* Get local variables. */ num_stations = oskar_telescope_num_stations(h->tel); num_src = h->max_sources_per_chunk; complx = (h->prec) | OSKAR_COMPLEX; vistype = complx; if (oskar_telescope_pol_mode(h->tel) == OSKAR_POL_MODE_FULL) vistype |= OSKAR_MATRIX; /* Expand the number of devices to the number of selected GPUs, * if required. */ if (h->num_devices < h->num_gpus) oskar_simulator_set_num_devices(h, h->num_gpus); for (i = 0; i < h->num_devices; ++i) { DeviceData* d = &h->d[i]; d->previous_chunk_index = -1; /* Select the device. */ if (i < h->num_gpus) { oskar_device_set(h->gpu_ids[i], status); dev_loc = OSKAR_GPU; } else { dev_loc = OSKAR_CPU; } /* Timers. */ if (!d->tmr_compute) { d->tmr_compute = oskar_timer_create(OSKAR_TIMER_NATIVE); d->tmr_copy = oskar_timer_create(OSKAR_TIMER_NATIVE); d->tmr_clip = oskar_timer_create(OSKAR_TIMER_NATIVE); d->tmr_E = oskar_timer_create(OSKAR_TIMER_NATIVE); d->tmr_K = oskar_timer_create(OSKAR_TIMER_NATIVE); d->tmr_join = oskar_timer_create(OSKAR_TIMER_NATIVE); d->tmr_correlate = oskar_timer_create(OSKAR_TIMER_NATIVE); } /* Visibility blocks. */ if (!d->vis_block) { d->vis_block = oskar_vis_block_create_from_header(dev_loc, h->header, status); d->vis_block_cpu[0] = oskar_vis_block_create_from_header(OSKAR_CPU, h->header, status); d->vis_block_cpu[1] = oskar_vis_block_create_from_header(OSKAR_CPU, h->header, status); } oskar_vis_block_clear(d->vis_block, status); oskar_vis_block_clear(d->vis_block_cpu[0], status); oskar_vis_block_clear(d->vis_block_cpu[1], status); /* Device scratch memory. */ if (!d->tel) { d->u = oskar_mem_create(h->prec, dev_loc, num_stations, status); d->v = oskar_mem_create(h->prec, dev_loc, num_stations, status); d->w = oskar_mem_create(h->prec, dev_loc, num_stations, status); d->chunk = oskar_sky_create(h->prec, dev_loc, num_src, status); d->chunk_clip = oskar_sky_create(h->prec, dev_loc, num_src, status); d->tel = oskar_telescope_create_copy(h->tel, dev_loc, status); d->J = oskar_jones_create(vistype, dev_loc, num_stations, num_src, status); d->R = oskar_type_is_matrix(vistype) ? oskar_jones_create(vistype, dev_loc, num_stations, num_src, status) : 0; d->E = oskar_jones_create(vistype, dev_loc, num_stations, num_src, status); d->K = oskar_jones_create(complx, dev_loc, num_stations, num_src, status); d->Z = 0; d->station_work = oskar_station_work_create(h->prec, dev_loc, status); } } }
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_evaluate_jones_Z(oskar_Jones* Z, const oskar_Sky* sky, const oskar_Telescope* telescope, const oskar_SettingsIonosphere* settings, double gast, double frequency_hz, oskar_WorkJonesZ* work, int* status) { int i, num_sources, num_stations; /* Station position in ECEF frame */ double station_x, station_y, station_z, wavelength; oskar_Mem *Z_station; int type; oskar_Sky* sky_cpu; /* Copy of the sky model on the CPU */ /* Check if safe to proceed. */ if (*status) return; /* Check data types. */ type = oskar_sky_precision(sky); if (oskar_telescope_precision(telescope) != type || oskar_jones_type(Z) != (type | OSKAR_COMPLEX) || oskar_work_jones_z_type(work) != type) { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } /* For now, this function requires data is on the CPU .. check this. */ /* Resize the work array (if needed) */ num_stations = oskar_telescope_num_stations(telescope); num_sources = oskar_sky_num_sources(sky); oskar_work_jones_z_resize(work, num_sources, status); /* Copy the sky model to the CPU. */ sky_cpu = oskar_sky_create_copy(sky, OSKAR_CPU, status); Z_station = oskar_mem_create_alias(0, 0, 0, status); wavelength = 299792458.0 / frequency_hz; /* Evaluate the ionospheric phase screen for each station at each * source pierce point. */ for (i = 0; i < num_stations; ++i) { double last, lon, lat; const oskar_Station* station; station = oskar_telescope_station_const(telescope, i); lon = oskar_station_lon_rad(station); lat = oskar_station_lat_rad(station); last = gast + lon; /* Evaluate horizontal x,y,z source positions (for which to evaluate * pierce points) */ oskar_convert_relative_directions_to_enu_directions( work->hor_x, work->hor_y, work->hor_z, num_sources, oskar_sky_l_const(sky_cpu), oskar_sky_m_const(sky_cpu), oskar_sky_n_const(sky_cpu), last - oskar_sky_reference_ra_rad(sky_cpu), oskar_sky_reference_dec_rad(sky_cpu), lat, status); /* Obtain station coordinates in the ECEF frame. */ evaluate_station_ECEF_coords(&station_x, &station_y, &station_z, i, telescope); /* Obtain the pierce points. */ /* FIXME(BM) this is current hard-coded to TID height screen 0 * this fix is only needed to support multiple screen heights. */ oskar_evaluate_pierce_points(work->pp_lon, work->pp_lat, work->pp_rel_path, station_x, station_y, station_z, settings->TID[0].height_km * 1000., num_sources, work->hor_x, work->hor_y, work->hor_z, status); /* Evaluate TEC values for the pierce points */ oskar_evaluate_TEC(work, num_sources, settings, gast, status); /* Get a pointer to the Jones matrices for the station */ oskar_jones_get_station_pointer(Z_station, Z, i, status); /* Populate the Jones matrix with ionospheric phase */ evaluate_jones_Z_station(Z_station, wavelength, work->total_TEC, work->hor_z, settings->min_elevation, num_sources, status); } oskar_sky_free(sky_cpu, status); oskar_mem_free(Z_station, status); }
int main(int argc, char** argv) { int status = 0; oskar::OptionParser opt("oskar_evaulate_pierce_points", oskar_version_string()); opt.add_required("settings file"); if (!opt.check_options(argc, argv)) return EXIT_FAILURE; const char* settings_file = opt.get_arg(); // Create the log. oskar_Log* log = oskar_log_create(OSKAR_LOG_MESSAGE, OSKAR_LOG_STATUS); oskar_log_message(log, 'M', 0, "Running binary %s", argv[0]); // Enum values used in writing time-freq data binary files enum OSKAR_TIME_FREQ_TAGS { TIME_IDX = 0, FREQ_IDX = 1, TIME_MJD_UTC = 2, FREQ_HZ = 3, NUM_FIELDS = 4, NUM_FIELD_TAGS = 5, HEADER_OFFSET = 10, DATA = 0, DIMS = 1, LABEL = 2, UNITS = 3, GRP = OSKAR_TAG_GROUP_TIME_FREQ_DATA }; oskar_Settings_old settings; oskar_settings_old_load(&settings, log, settings_file, &status); oskar_log_set_keep_file(log, settings.sim.keep_log_file); if (status) return status; oskar_Telescope* tel = oskar_settings_to_telescope(&settings, log, &status); oskar_Sky* sky = oskar_settings_to_sky(&settings, log, &status); // FIXME remove this restriction ... (see evaluate Z) if (settings.ionosphere.num_TID_screens != 1) return OSKAR_ERR_SETUP_FAIL; int type = settings.sim.double_precision ? OSKAR_DOUBLE : OSKAR_SINGLE; int loc = OSKAR_CPU; int num_sources = oskar_sky_num_sources(sky); oskar_Mem *hor_x, *hor_y, *hor_z; hor_x = oskar_mem_create(type, loc, num_sources, &status); hor_y = oskar_mem_create(type, loc, num_sources, &status); hor_z = oskar_mem_create(type, loc, num_sources, &status); oskar_Mem *pp_lon, *pp_lat, *pp_rel_path; int num_stations = oskar_telescope_num_stations(tel); int num_pp = num_stations * num_sources; pp_lon = oskar_mem_create(type, loc, num_pp, &status); pp_lat = oskar_mem_create(type, loc, num_pp, &status); pp_rel_path = oskar_mem_create(type, loc, num_pp, &status); // Pierce points for one station (non-owned oskar_Mem pointers) oskar_Mem *pp_st_lon, *pp_st_lat, *pp_st_rel_path; pp_st_lon = oskar_mem_create_alias(0, 0, 0, &status); pp_st_lat = oskar_mem_create_alias(0, 0, 0, &status); pp_st_rel_path = oskar_mem_create_alias(0, 0, 0, &status); int num_times = settings.obs.num_time_steps; double obs_start_mjd_utc = settings.obs.start_mjd_utc; double dt_dump = settings.obs.dt_dump_days; // Binary file meta-data std::string label1 = "pp_lon"; std::string label2 = "pp_lat"; std::string label3 = "pp_path"; std::string units = "radians"; std::string units2 = ""; oskar_Mem *dims = oskar_mem_create(OSKAR_INT, loc, 2, &status); /* FIXME is this the correct dimension order ? * FIXME get the MATLAB reader to respect dimension ordering */ oskar_mem_int(dims, &status)[0] = num_sources; oskar_mem_int(dims, &status)[1] = num_stations; const char* filename = settings.ionosphere.pierce_points.filename; oskar_Binary* h = oskar_binary_create(filename, 'w', &status); double screen_height_m = settings.ionosphere.TID->height_km * 1000.0; // printf("Number of times = %i\n", num_times); // printf("Number of stations = %i\n", num_stations); void *x_, *y_, *z_; x_ = oskar_mem_void(oskar_telescope_station_true_x_offset_ecef_metres(tel)); y_ = oskar_mem_void(oskar_telescope_station_true_y_offset_ecef_metres(tel)); z_ = oskar_mem_void(oskar_telescope_station_true_z_offset_ecef_metres(tel)); for (int t = 0; t < num_times; ++t) { double t_dump = obs_start_mjd_utc + t * dt_dump; // MJD UTC double gast = oskar_convert_mjd_to_gast_fast(t_dump + dt_dump / 2.0); for (int i = 0; i < num_stations; ++i) { const oskar_Station* station = oskar_telescope_station_const(tel, i); double lon = oskar_station_lon_rad(station); double lat = oskar_station_lat_rad(station); double alt = oskar_station_alt_metres(station); double x_ecef, y_ecef, z_ecef, x_offset, y_offset, z_offset; if (type == OSKAR_DOUBLE) { x_offset = ((double*)x_)[i]; y_offset = ((double*)y_)[i]; z_offset = ((double*)z_)[i]; } else { x_offset = (double)((float*)x_)[i]; y_offset = (double)((float*)y_)[i]; z_offset = (double)((float*)z_)[i]; } oskar_convert_offset_ecef_to_ecef(1, &x_offset, &y_offset, &z_offset, lon, lat, alt, &x_ecef, &y_ecef, &z_ecef); double last = gast + lon; if (type == OSKAR_DOUBLE) { oskar_convert_apparent_ra_dec_to_enu_directions_d(num_sources, oskar_mem_double_const(oskar_sky_ra_rad_const(sky), &status), oskar_mem_double_const(oskar_sky_dec_rad_const(sky), &status), last, lat, oskar_mem_double(hor_x, &status), oskar_mem_double(hor_y, &status), oskar_mem_double(hor_z, &status)); } else { oskar_convert_apparent_ra_dec_to_enu_directions_f(num_sources, oskar_mem_float_const(oskar_sky_ra_rad_const(sky), &status), oskar_mem_float_const(oskar_sky_dec_rad_const(sky), &status), last, lat, oskar_mem_float(hor_x, &status), oskar_mem_float(hor_y, &status), oskar_mem_float(hor_z, &status)); } int offset = i * num_sources; oskar_mem_set_alias(pp_st_lon, pp_lon, offset, num_sources, &status); oskar_mem_set_alias(pp_st_lat, pp_lat, offset, num_sources, &status); oskar_mem_set_alias(pp_st_rel_path, pp_rel_path, offset, num_sources, &status); oskar_evaluate_pierce_points(pp_st_lon, pp_st_lat, pp_st_rel_path, x_ecef, y_ecef, z_ecef, screen_height_m, num_sources, hor_x, hor_y, hor_z, &status); } // Loop over stations. if (status != 0) continue; int index = t; // could be = (num_times * f) + t if we have frequency data int num_fields = 3; int num_field_tags = 4; double freq_hz = 0.0; int freq_idx = 0; // Write the header TAGS oskar_binary_write_int(h, GRP, TIME_IDX, index, t, &status); oskar_binary_write_double(h, GRP, FREQ_IDX, index, freq_idx, &status); oskar_binary_write_double(h, GRP, TIME_MJD_UTC, index, t_dump, &status); oskar_binary_write_double(h, GRP, FREQ_HZ, index, freq_hz, &status); oskar_binary_write_int(h, GRP, NUM_FIELDS, index, num_fields, &status); oskar_binary_write_int(h, GRP, NUM_FIELD_TAGS, index, num_field_tags, &status); // Write data TAGS (fields) int field, tagID; field = 0; tagID = HEADER_OFFSET + (num_field_tags * field); oskar_binary_write_mem(h, pp_lon, GRP, tagID + DATA, index, 0, &status); oskar_binary_write_mem(h, dims, GRP, tagID + DIMS, index, 0, &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL, index, label1.size()+1, label1.c_str(), &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS, index, units.size()+1, units.c_str(), &status); field = 1; tagID = HEADER_OFFSET + (num_field_tags * field); oskar_binary_write_mem(h, pp_lat, GRP, tagID + DATA, index, 0, &status); oskar_binary_write_mem(h, dims, GRP, tagID + DIMS, index, 0, &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL, index, label2.size()+1, label2.c_str(), &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS, index, units.size()+1, units.c_str(), &status); field = 2; tagID = HEADER_OFFSET + (num_field_tags * field); oskar_binary_write_mem(h, pp_rel_path, GRP, tagID + DATA, index, 0, &status); oskar_binary_write_mem(h, dims, GRP, tagID + DIMS, index, 0, &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL, index, label3.size()+1, label3.c_str(), &status); oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS, index, units2.size()+1, units2.c_str(), &status); } // Loop over times // Close the OSKAR binary file. oskar_binary_free(h); // clean up memory oskar_mem_free(hor_x, &status); oskar_mem_free(hor_y, &status); oskar_mem_free(hor_z, &status); oskar_mem_free(pp_lon, &status); oskar_mem_free(pp_lat, &status); oskar_mem_free(pp_rel_path, &status); oskar_mem_free(pp_st_lon, &status); oskar_mem_free(pp_st_lat, &status); oskar_mem_free(pp_st_rel_path, &status); oskar_mem_free(dims, &status); oskar_telescope_free(tel, &status); oskar_sky_free(sky, &status); // Check for errors. if (status) oskar_log_error(log, "Run failed: %s.", oskar_get_error_string(status)); oskar_log_free(log); return 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); }