void oskar_imager_check_init(oskar_Imager* h, int* status) { /* Don't initialise if we're in "coords only" mode. */ if (h->coords_only) return; oskar_timer_resume(h->tmr_init); switch (h->algorithm) { case OSKAR_ALGORITHM_DFT_2D: case OSKAR_ALGORITHM_DFT_3D: { if (!h->l) oskar_imager_init_dft(h, status); break; } case OSKAR_ALGORITHM_FFT: { if (!h->conv_func) oskar_imager_init_fft(h, status); break; } case OSKAR_ALGORITHM_WPROJ: { if (!h->w_kernels) oskar_imager_init_wproj(h, status); break; } default: *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE; } oskar_timer_pause(h->tmr_init); }
void oskar_simulator_write_block(oskar_Simulator* h, const oskar_VisBlock* block, int block_index, int* status) { if (*status) return; /* Open files only if required, and write the block into them. */ oskar_timer_resume(h->tmr_write); #ifndef OSKAR_NO_MS if (h->ms_name && !h->ms) h->ms = oskar_vis_header_write_ms(h->header, h->ms_name, OSKAR_TRUE, h->force_polarised_ms, status); if (h->ms) oskar_vis_block_write_ms(block, h->header, h->ms, status); #endif if (h->vis_name && !h->vis) h->vis = oskar_vis_header_write(h->header, h->vis_name, status); if (h->vis) oskar_vis_block_write(block, h->vis, block_index, status); oskar_timer_pause(h->tmr_write); }
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); }
void oskar_simulator_run_block(oskar_Simulator* h, int block_index, int device_id, int* status) { double obs_start_mjd, dt_dump_days; int i_active, time_index_start, time_index_end; int num_channels, num_times_block, total_chunks, total_times; DeviceData* d; if (*status) return; /* Check that initialisation has happened. We can't initialise here, * as we're already multi-threaded at this point. */ if (!h->header) { *status = OSKAR_ERR_MEMORY_NOT_ALLOCATED; oskar_log_error(h->log, "Simulator not initalised. " "Call oskar_simulator_check_init() first."); return; } #ifdef _OPENMP if (!h->coords_only) { /* Disable any nested parallelism. */ omp_set_num_threads(1); omp_set_nested(0); } #endif /* Set the GPU to use. (Supposed to be a very low-overhead call.) */ if (device_id >= 0 && device_id < h->num_gpus) oskar_device_set(h->gpu_ids[device_id], status); /* Clear the visibility block. */ i_active = block_index % 2; /* Index of the active buffer. */ d = &(h->d[device_id]); oskar_timer_resume(d->tmr_compute); oskar_vis_block_clear(d->vis_block, status); /* Set the visibility block meta-data. */ total_chunks = h->num_sky_chunks; num_channels = h->num_channels; total_times = h->num_time_steps; obs_start_mjd = h->time_start_mjd_utc; dt_dump_days = h->time_inc_sec / 86400.0; time_index_start = block_index * h->max_times_per_block; time_index_end = time_index_start + h->max_times_per_block - 1; if (time_index_end >= total_times) time_index_end = total_times - 1; num_times_block = 1 + time_index_end - time_index_start; /* Set the number of active times in the block. */ oskar_vis_block_set_num_times(d->vis_block, num_times_block, status); oskar_vis_block_set_start_time_index(d->vis_block, time_index_start); /* Go though all possible work units in the block. A work unit is defined * as the simulation for one time and one sky chunk. */ while (!h->coords_only) { oskar_Sky* sky; int i_work_unit, i_chunk, i_time, i_channel, sim_time_idx; oskar_mutex_lock(h->mutex); i_work_unit = (h->work_unit_index)++; oskar_mutex_unlock(h->mutex); if ((i_work_unit >= num_times_block * total_chunks) || *status) break; /* Convert slice index to chunk/time index. */ i_chunk = i_work_unit / num_times_block; i_time = i_work_unit - i_chunk * num_times_block; sim_time_idx = time_index_start + i_time; /* Copy sky chunk to device only if different from the previous one. */ if (i_chunk != d->previous_chunk_index) { oskar_timer_resume(d->tmr_copy); oskar_sky_copy(d->chunk, h->sky_chunks[i_chunk], status); oskar_timer_pause(d->tmr_copy); } sky = h->apply_horizon_clip ? d->chunk_clip : d->chunk; /* Apply horizon clip if required. */ if (h->apply_horizon_clip) { double gast, mjd; mjd = obs_start_mjd + dt_dump_days * (sim_time_idx + 0.5); gast = oskar_convert_mjd_to_gast_fast(mjd); oskar_timer_resume(d->tmr_clip); oskar_sky_horizon_clip(d->chunk_clip, d->chunk, d->tel, gast, d->station_work, status); oskar_timer_pause(d->tmr_clip); } /* Simulate all baselines for all channels for this time and chunk. */ for (i_channel = 0; i_channel < num_channels; ++i_channel) { if (*status) break; if (h->log) { oskar_mutex_lock(h->mutex); oskar_log_message(h->log, 'S', 1, "Time %*i/%i, " "Chunk %*i/%i, Channel %*i/%i [Device %i, %i sources]", disp_width(total_times), sim_time_idx + 1, total_times, disp_width(total_chunks), i_chunk + 1, total_chunks, disp_width(num_channels), i_channel + 1, num_channels, device_id, oskar_sky_num_sources(sky)); oskar_mutex_unlock(h->mutex); } sim_baselines(h, d, sky, i_channel, i_time, sim_time_idx, status); } d->previous_chunk_index = i_chunk; } /* Copy the visibility block to host memory. */ oskar_timer_resume(d->tmr_copy); oskar_vis_block_copy(d->vis_block_cpu[i_active], d->vis_block, status); oskar_timer_pause(d->tmr_copy); oskar_timer_pause(d->tmr_compute); }
void oskar_imager_read_coords_ms(oskar_Imager* h, const char* filename, int i_file, int num_files, int* percent_done, int* percent_next, int* status) { #ifndef OSKAR_NO_MS oskar_MeasurementSet* ms; oskar_Mem *uvw, *u, *v, *w, *weight, *time_centroid; int num_channels, num_stations, num_baselines, num_pols; int start_row, num_rows; double *uvw_, *u_, *v_, *w_; if (*status) return; /* Read the header. */ ms = oskar_ms_open(filename); if (!ms) { *status = OSKAR_ERR_FILE_IO; return; } num_rows = (int) oskar_ms_num_rows(ms); num_stations = (int) oskar_ms_num_stations(ms); num_baselines = num_stations * (num_stations - 1) / 2; num_pols = (int) oskar_ms_num_pols(ms); num_channels = (int) oskar_ms_num_channels(ms); /* Set visibility meta-data. */ oskar_imager_set_vis_frequency(h, oskar_ms_freq_start_hz(ms), oskar_ms_freq_inc_hz(ms), num_channels); oskar_imager_set_vis_phase_centre(h, oskar_ms_phase_centre_ra_rad(ms) * 180/M_PI, oskar_ms_phase_centre_dec_rad(ms) * 180/M_PI); /* Create arrays. */ uvw = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 3 * num_baselines, status); u = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, num_baselines, status); v = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, num_baselines, status); w = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, num_baselines, status); weight = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU, num_baselines * num_pols, status); time_centroid = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, num_baselines, status); uvw_ = oskar_mem_double(uvw, status); u_ = oskar_mem_double(u, status); v_ = oskar_mem_double(v, status); w_ = oskar_mem_double(w, status); /* Loop over visibility blocks. */ for (start_row = 0; start_row < num_rows; start_row += num_baselines) { int i, block_size; size_t allocated, required; if (*status) break; /* Read coordinates and weights from Measurement Set. */ oskar_timer_resume(h->tmr_read); block_size = num_rows - start_row; if (block_size > num_baselines) block_size = num_baselines; allocated = oskar_mem_length(uvw) * oskar_mem_element_size(oskar_mem_type(uvw)); oskar_ms_read_column(ms, "UVW", start_row, block_size, allocated, oskar_mem_void(uvw), &required, status); allocated = oskar_mem_length(weight) * oskar_mem_element_size(oskar_mem_type(weight)); oskar_ms_read_column(ms, "WEIGHT", start_row, block_size, allocated, oskar_mem_void(weight), &required, status); allocated = oskar_mem_length(time_centroid) * oskar_mem_element_size(oskar_mem_type(time_centroid)); oskar_ms_read_column(ms, "TIME_CENTROID", start_row, block_size, allocated, oskar_mem_void(time_centroid), &required, status); /* Split up baseline coordinates. */ for (i = 0; i < block_size; ++i) { u_[i] = uvw_[3*i + 0]; v_[i] = uvw_[3*i + 1]; w_[i] = uvw_[3*i + 2]; } /* Update the imager with the data. */ oskar_timer_pause(h->tmr_read); oskar_imager_update(h, block_size, 0, num_channels - 1, num_pols, u, v, w, 0, weight, time_centroid, status); *percent_done = (int) round(100.0 * ( (start_row + block_size) / (double)(num_rows * 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(uvw, status); oskar_mem_free(u, status); oskar_mem_free(v, status); oskar_mem_free(w, status); oskar_mem_free(weight, status); oskar_mem_free(time_centroid, status); oskar_ms_close(ms); #else (void) filename; (void) i_file; (void) num_files; (void) percent_done; (void) percent_next; oskar_log_error(h->log, "OSKAR was compiled without Measurement Set support."); *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE; #endif }
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); }