oskar_Telescope* oskar_telescope_create_copy(const oskar_Telescope* src, int location, int* status) { int i = 0; oskar_Telescope* telescope; /* Create a new, empty model. */ telescope = oskar_telescope_create(oskar_telescope_precision(src), location, 0, status); /* Copy private meta-data. */ telescope->precision = src->precision; telescope->mem_location = location; /* Copy the meta-data. */ telescope->pol_mode = src->pol_mode; telescope->num_stations = src->num_stations; telescope->max_station_size = src->max_station_size; telescope->max_station_depth = src->max_station_depth; telescope->identical_stations = src->identical_stations; telescope->allow_station_beam_duplication = src->allow_station_beam_duplication; telescope->enable_numerical_patterns = src->enable_numerical_patterns; telescope->lon_rad = src->lon_rad; telescope->lat_rad = src->lat_rad; telescope->alt_metres = src->alt_metres; telescope->pm_x_rad = src->pm_x_rad; telescope->pm_y_rad = src->pm_y_rad; telescope->phase_centre_coord_type = src->phase_centre_coord_type; telescope->phase_centre_ra_rad = src->phase_centre_ra_rad; telescope->phase_centre_dec_rad = src->phase_centre_dec_rad; telescope->channel_bandwidth_hz = src->channel_bandwidth_hz; telescope->time_average_sec = src->time_average_sec; telescope->uv_filter_min = src->uv_filter_min; telescope->uv_filter_max = src->uv_filter_max; telescope->uv_filter_units = src->uv_filter_units; telescope->noise_enabled = src->noise_enabled; telescope->noise_seed = src->noise_seed; /* Copy the coordinates. */ oskar_mem_copy(telescope->station_true_x_offset_ecef_metres, src->station_true_x_offset_ecef_metres, status); oskar_mem_copy(telescope->station_true_y_offset_ecef_metres, src->station_true_y_offset_ecef_metres, status); oskar_mem_copy(telescope->station_true_z_offset_ecef_metres, src->station_true_z_offset_ecef_metres, status); oskar_mem_copy(telescope->station_true_x_enu_metres, src->station_true_x_enu_metres, status); oskar_mem_copy(telescope->station_true_y_enu_metres, src->station_true_y_enu_metres, status); oskar_mem_copy(telescope->station_true_z_enu_metres, src->station_true_z_enu_metres, status); oskar_mem_copy(telescope->station_measured_x_offset_ecef_metres, src->station_measured_x_offset_ecef_metres, status); oskar_mem_copy(telescope->station_measured_y_offset_ecef_metres, src->station_measured_y_offset_ecef_metres, status); oskar_mem_copy(telescope->station_measured_z_offset_ecef_metres, src->station_measured_z_offset_ecef_metres, status); oskar_mem_copy(telescope->station_measured_x_enu_metres, src->station_measured_x_enu_metres, status); oskar_mem_copy(telescope->station_measured_y_enu_metres, src->station_measured_y_enu_metres, status); oskar_mem_copy(telescope->station_measured_z_enu_metres, src->station_measured_z_enu_metres, status); /* Copy each station. */ telescope->station = malloc(src->num_stations * sizeof(oskar_Station*)); for (i = 0; i < src->num_stations; ++i) { telescope->station[i] = oskar_station_create_copy( oskar_telescope_station_const(src, i), location, status); } /* Return pointer to data structure. */ return telescope; }
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); }