TEST(Mem, random_gaussian_accum) { int status = 0; int seed = 1; int blocksize = 256; int rounds = 10240; oskar_Mem* block = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, blocksize, &status); oskar_Mem* total = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, blocksize * rounds, &status); for (int i = 0; i < rounds; ++i) { oskar_mem_random_gaussian(block, seed, i, 0, 0, 1.0, &status); oskar_mem_copy_contents(total, block, i * blocksize, 0, blocksize, &status); } ASSERT_EQ(0, status) << oskar_get_error_string(status); if (save) { FILE* fhan = fopen("random_gaussian_accum.txt", "w"); oskar_mem_save_ascii(fhan, 1, blocksize * rounds, &status, total); fclose(fhan); } oskar_mem_free(block, &status); oskar_mem_free(total, &status); }
oskar_Mem* oskar_mem_create_copy(const oskar_Mem* src, int location, int* status) { oskar_Mem* mem = 0; /* Check if safe to proceed. */ if (*status) return 0; /* Create the new structure. */ mem = oskar_mem_create(oskar_mem_type(src), location, oskar_mem_length(src), status); if (!mem || *status) return mem; /* Copy the memory. */ oskar_mem_copy_contents(mem, src, 0, 0, oskar_mem_length(src), status); /* Return a handle to the new structure. */ return mem; }
void oskar_evaluate_station_beam(oskar_Mem* beam_pattern, int num_points, int coord_type, oskar_Mem* x, oskar_Mem* y, oskar_Mem* z, double norm_ra_rad, double norm_dec_rad, const oskar_Station* station, oskar_StationWork* work, int time_index, double frequency_hz, double GAST, int* status) { int normalise_final_beam; oskar_Mem* out; /* Check if safe to proceed. */ if (*status) return; /* Set default output beam array. */ out = beam_pattern; /* Check that the arrays have enough space to add an extra source at the * end (for normalisation). We don't want to reallocate here, since that * will be slow to do each time: must simply ensure that we pass input * arrays that are large enough. * The normalisation doesn't need to happen if the station has an * isotropic beam. */ normalise_final_beam = oskar_station_normalise_final_beam(station) && (oskar_station_type(station) != OSKAR_STATION_TYPE_ISOTROPIC); if (normalise_final_beam) { double c_x = 0.0, c_y = 0.0, c_z = 1.0; /* Increment number of points. */ num_points++; /* Check the input arrays are big enough to hold the new source. */ if ((int)oskar_mem_length(x) < num_points || (int)oskar_mem_length(y) < num_points || (int)oskar_mem_length(z) < num_points) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } /* Set output beam array to work buffer. */ out = oskar_station_work_normalised_beam(work, beam_pattern, status); /* Get the beam direction in the appropriate coordinate system. */ /* (Direction cosines are already set to the interferometer phase * centre for relative directions.) */ if (coord_type == OSKAR_ENU_DIRECTIONS) { double t_x, t_y, t_z, ha0; ha0 = (GAST + oskar_station_lon_rad(station)) - norm_ra_rad; oskar_convert_relative_directions_to_enu_directions_d( &t_x, &t_y, &t_z, 1, &c_x, &c_y, &c_z, ha0, norm_dec_rad, oskar_station_lat_rad(station)); c_x = t_x; c_y = t_y; c_z = t_z; } /* Add the extra normalisation source to the end of the arrays. */ oskar_mem_set_element_real(x, num_points-1, c_x, status); oskar_mem_set_element_real(y, num_points-1, c_y, status); oskar_mem_set_element_real(z, num_points-1, c_z, status); } /* Evaluate the station beam for the given directions. */ if (coord_type == OSKAR_ENU_DIRECTIONS) { evaluate_station_beam_enu_directions(out, num_points, x, y, z, station, work, time_index, frequency_hz, GAST, status); } else if (coord_type == OSKAR_RELATIVE_DIRECTIONS) { evaluate_station_beam_relative_directions(out, num_points, x, y, z, station, work, time_index, frequency_hz, GAST, status); } else { *status = OSKAR_ERR_INVALID_ARGUMENT; } /* Scale beam pattern by value of the last source if required. */ if (normalise_final_beam) { double amp = 0.0; /* Get the last element of the vector and convert to amplitude. */ if (oskar_mem_is_matrix(out)) { double4c val; val = oskar_mem_get_element_matrix(out, num_points-1, status); /* * Scale by square root of "Stokes I" autocorrelation: * sqrt(0.5 * [sum of resultant diagonal]). * * We have * [ Xa Xb ] [ Xa* Xc* ] = [ Xa Xa* + Xb Xb* (don't care) ] * [ Xc Xd ] [ Xb* Xd* ] [ (don't care) Xc Xc* + Xd Xd* ] * * Stokes I is completely real, so need only evaluate the real * part of all the multiplies. Because of the conjugate terms, * these become re*re + im*im. * * Need the square root because we only want the normalised value * for the beam itself (in isolation), not its actual * autocorrelation! */ amp = val.a.x * val.a.x + val.a.y * val.a.y + val.b.x * val.b.x + val.b.y * val.b.y + val.c.x * val.c.x + val.c.y * val.c.y + val.d.x * val.d.x + val.d.y * val.d.y; amp = sqrt(0.5 * amp); } else { double2 val; val = oskar_mem_get_element_complex(out, num_points-1, status); /* Scale by voltage. */ amp = sqrt(val.x * val.x + val.y * val.y); } /* Scale beam array by normalisation value. */ oskar_mem_scale_real(out, 1.0/amp, status); /* Copy output beam data. */ oskar_mem_copy_contents(beam_pattern, out, 0, 0, num_points-1, status); } }
void oskar_sky_copy(oskar_Sky* dst, const oskar_Sky* src, int* status) { int num_sources; /* Check if safe to proceed. */ if (*status) return; if (oskar_sky_precision(dst) != oskar_sky_precision(src)) { *status = OSKAR_ERR_BAD_DATA_TYPE; return; } if (oskar_sky_capacity(dst) < oskar_sky_capacity(src)) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } /* Copy meta data */ num_sources = src->num_sources; dst->num_sources = num_sources; dst->use_extended = src->use_extended; dst->reference_ra_rad = src->reference_ra_rad; dst->reference_dec_rad = src->reference_dec_rad; /* Copy the memory blocks */ oskar_mem_copy_contents(dst->ra_rad, src->ra_rad, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->dec_rad, src->dec_rad, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->I, src->I, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->Q, src->Q, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->U, src->U, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->V, src->V, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->reference_freq_hz, src->reference_freq_hz, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->spectral_index, src->spectral_index, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->rm_rad, src->rm_rad, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->l, src->l, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->m, src->m, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->n, src->n, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->fwhm_major_rad, src->fwhm_major_rad, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->fwhm_minor_rad, src->fwhm_minor_rad, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->pa_rad, src->pa_rad, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->gaussian_a, src->gaussian_a, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->gaussian_b, src->gaussian_b, 0, 0, num_sources, status); oskar_mem_copy_contents(dst->gaussian_c, src->gaussian_c, 0, 0, num_sources, status); }
static PyObject* append_sources(PyObject* self, PyObject* args) { oskar_Sky *h = 0; PyObject *obj[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; oskar_Mem *ra_c, *dec_c, *I_c, *Q_c, *U_c, *V_c; oskar_Mem *ref_c, *spix_c, *rm_c, *maj_c, *min_c, *pa_c; PyArrayObject *ra = 0, *dec = 0, *I = 0, *Q = 0, *U = 0, *V = 0; PyArrayObject *ref = 0, *spix = 0, *rm = 0, *maj = 0, *min = 0, *pa = 0; int status = 0, npy_type, type, flags, num_sources, old_num; /* Parse inputs: RA, Dec, I, Q, U, V, ref, spix, rm, maj, min, pa. */ if (!PyArg_ParseTuple(args, "OOOOOOOOOOOOO", &obj[0], &obj[1], &obj[2], &obj[3], &obj[4], &obj[5], &obj[6], &obj[7], &obj[8], &obj[9], &obj[10], &obj[11], &obj[12])) return 0; if (!(h = get_handle(obj[0]))) return 0; /* Make sure input objects are arrays. Convert if required. */ flags = NPY_ARRAY_FORCECAST | NPY_ARRAY_IN_ARRAY; type = oskar_sky_precision(h); npy_type = numpy_type_from_oskar(type); ra = (PyArrayObject*) PyArray_FROM_OTF(obj[1], npy_type, flags); dec = (PyArrayObject*) PyArray_FROM_OTF(obj[2], npy_type, flags); I = (PyArrayObject*) PyArray_FROM_OTF(obj[3], npy_type, flags); Q = (PyArrayObject*) PyArray_FROM_OTF(obj[4], npy_type, flags); U = (PyArrayObject*) PyArray_FROM_OTF(obj[5], npy_type, flags); V = (PyArrayObject*) PyArray_FROM_OTF(obj[6], npy_type, flags); ref = (PyArrayObject*) PyArray_FROM_OTF(obj[7], npy_type, flags); spix = (PyArrayObject*) PyArray_FROM_OTF(obj[8], npy_type, flags); rm = (PyArrayObject*) PyArray_FROM_OTF(obj[9], npy_type, flags); maj = (PyArrayObject*) PyArray_FROM_OTF(obj[10], npy_type, flags); min = (PyArrayObject*) PyArray_FROM_OTF(obj[11], npy_type, flags); pa = (PyArrayObject*) PyArray_FROM_OTF(obj[12], npy_type, flags); if (!ra || !dec || !I || !Q || !U || !V || !ref || !spix || !rm || !maj || !min || !pa) goto fail; /* Check size of input arrays. */ num_sources = (int) PyArray_SIZE(I); if (num_sources != (int) PyArray_SIZE(ra) || num_sources != (int) PyArray_SIZE(dec) || num_sources != (int) PyArray_SIZE(Q) || num_sources != (int) PyArray_SIZE(U) || num_sources != (int) PyArray_SIZE(V) || num_sources != (int) PyArray_SIZE(ref) || num_sources != (int) PyArray_SIZE(spix) || num_sources != (int) PyArray_SIZE(rm) || num_sources != (int) PyArray_SIZE(maj) || num_sources != (int) PyArray_SIZE(min) || num_sources != (int) PyArray_SIZE(pa)) { PyErr_SetString(PyExc_RuntimeError, "Input data dimension mismatch."); goto fail; } /* Pointers to input arrays. */ ra_c = oskar_mem_create_alias_from_raw(PyArray_DATA(ra), type, OSKAR_CPU, num_sources, &status); dec_c = oskar_mem_create_alias_from_raw(PyArray_DATA(dec), type, OSKAR_CPU, num_sources, &status); I_c = oskar_mem_create_alias_from_raw(PyArray_DATA(I), type, OSKAR_CPU, num_sources, &status); Q_c = oskar_mem_create_alias_from_raw(PyArray_DATA(Q), type, OSKAR_CPU, num_sources, &status); U_c = oskar_mem_create_alias_from_raw(PyArray_DATA(U), type, OSKAR_CPU, num_sources, &status); V_c = oskar_mem_create_alias_from_raw(PyArray_DATA(V), type, OSKAR_CPU, num_sources, &status); ref_c = oskar_mem_create_alias_from_raw(PyArray_DATA(ref), type, OSKAR_CPU, num_sources, &status); spix_c = oskar_mem_create_alias_from_raw(PyArray_DATA(spix), type, OSKAR_CPU, num_sources, &status); rm_c = oskar_mem_create_alias_from_raw(PyArray_DATA(rm), type, OSKAR_CPU, num_sources, &status); maj_c = oskar_mem_create_alias_from_raw(PyArray_DATA(maj), type, OSKAR_CPU, num_sources, &status); min_c = oskar_mem_create_alias_from_raw(PyArray_DATA(min), type, OSKAR_CPU, num_sources, &status); pa_c = oskar_mem_create_alias_from_raw(PyArray_DATA(pa), type, OSKAR_CPU, num_sources, &status); /* Copy source data into the sky model. */ old_num = oskar_sky_num_sources(h); oskar_sky_resize(h, old_num + num_sources, &status); oskar_mem_copy_contents(oskar_sky_ra_rad(h), ra_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_dec_rad(h), dec_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_I(h), I_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_Q(h), Q_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_U(h), U_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_V(h), V_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_reference_freq_hz(h), ref_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_spectral_index(h), spix_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_rotation_measure_rad(h), rm_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_fwhm_major_rad(h), maj_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_fwhm_minor_rad(h), min_c, old_num, 0, num_sources, &status); oskar_mem_copy_contents(oskar_sky_position_angle_rad(h), pa_c, old_num, 0, num_sources, &status); /* Free memory. */ oskar_mem_free(ra_c, &status); oskar_mem_free(dec_c, &status); oskar_mem_free(I_c, &status); oskar_mem_free(Q_c, &status); oskar_mem_free(U_c, &status); oskar_mem_free(V_c, &status); oskar_mem_free(ref_c, &status); oskar_mem_free(spix_c, &status); oskar_mem_free(rm_c, &status); oskar_mem_free(maj_c, &status); oskar_mem_free(min_c, &status); oskar_mem_free(pa_c, &status); /* Check for errors. */ if (status) { PyErr_Format(PyExc_RuntimeError, "Sky model append_sources() failed with code %d (%s).", status, oskar_get_error_string(status)); goto fail; } Py_XDECREF(ra); Py_XDECREF(dec); Py_XDECREF(I); Py_XDECREF(Q); Py_XDECREF(U); Py_XDECREF(V); Py_XDECREF(ref); Py_XDECREF(spix); Py_XDECREF(rm); Py_XDECREF(maj); Py_XDECREF(min); Py_XDECREF(pa); return Py_BuildValue(""); fail: Py_XDECREF(ra); Py_XDECREF(dec); Py_XDECREF(I); Py_XDECREF(Q); Py_XDECREF(U); Py_XDECREF(V); Py_XDECREF(ref); Py_XDECREF(spix); Py_XDECREF(rm); Py_XDECREF(maj); Py_XDECREF(min); Py_XDECREF(pa); return 0; }
static void oskar_evaluate_station_beam_aperture_array_private(oskar_Mem* beam, const oskar_Station* s, int num_points, const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z, double gast, double frequency_hz, oskar_StationWork* work, int time_index, int depth, int* status) { double beam_x, beam_y, beam_z, wavenumber; oskar_Mem *weights, *weights_error, *theta, *phi, *array; int num_elements, is_3d; num_elements = oskar_station_num_elements(s); is_3d = oskar_station_array_is_3d(s); weights = work->weights; weights_error = work->weights_error; theta = work->theta_modified; phi = work->phi_modified; array = work->array_pattern; wavenumber = 2.0 * M_PI * frequency_hz / 299792458.0; /* Check if safe to proceed. */ if (*status) return; /* Compute direction cosines for the beam for this station. */ oskar_evaluate_beam_horizon_direction(&beam_x, &beam_y, &beam_z, s, gast, status); /* Evaluate beam if there are no child stations. */ if (!oskar_station_has_child(s)) { /* First optimisation: A single element model type, and either a common * orientation for all elements within the station, or isotropic * elements. */ /* Array pattern and element pattern are separable. */ if (oskar_station_num_element_types(s) == 1 && (oskar_station_common_element_orientation(s) || oskar_element_type(oskar_station_element_const(s, 0)) == OSKAR_ELEMENT_TYPE_ISOTROPIC) ) { /* (Always) evaluate element pattern into the output beam array. */ oskar_element_evaluate(oskar_station_element_const(s, 0), beam, oskar_station_element_x_alpha_rad(s, 0) + M_PI/2.0, /* FIXME Will change: This matches the old convention. */ oskar_station_element_y_alpha_rad(s, 0), num_points, x, y, z, frequency_hz, theta, phi, status); /* Check if array pattern is enabled. */ if (oskar_station_enable_array_pattern(s)) { /* Generate beamforming weights and evaluate array pattern. */ oskar_evaluate_element_weights(weights, weights_error, wavenumber, s, beam_x, beam_y, beam_z, time_index, status); oskar_dftw(num_elements, wavenumber, oskar_station_element_true_x_enu_metres_const(s), oskar_station_element_true_y_enu_metres_const(s), oskar_station_element_true_z_enu_metres_const(s), weights, num_points, x, y, (is_3d ? z : 0), 0, array, status); /* Normalise array response if required. */ if (oskar_station_normalise_array_pattern(s)) oskar_mem_scale_real(array, 1.0 / num_elements, status); /* Element-wise multiply to join array and element pattern. */ oskar_mem_multiply(beam, beam, array, num_points, status); } } #if 0 /* Second optimisation: Common orientation for all elements within the * station, but more than one element type. */ else if (oskar_station_common_element_orientation(s)) { /* Must evaluate array pattern, so check that this is enabled. */ if (!oskar_station_enable_array_pattern(s)) { *status = OSKAR_ERR_SETTINGS_TELESCOPE; return; } /* Call a DFT using indexed input. */ /* TODO Not yet implemented. */ *status = OSKAR_ERR_FUNCTION_NOT_AVAILABLE; } #endif /* No optimisation: No common element orientation. */ /* Can't separate array and element evaluation. */ else { int i, num_element_types; oskar_Mem *element_block = 0, *element = 0; const int* element_type_array = 0; /* Must evaluate array pattern, so check that this is enabled. */ if (!oskar_station_enable_array_pattern(s)) { *status = OSKAR_ERR_SETTINGS_TELESCOPE; return; } /* Get sized element pattern block (at depth 0). */ element_block = oskar_station_work_beam(work, beam, num_elements * num_points, 0, status); /* Create alias into element block. */ element = oskar_mem_create_alias(element_block, 0, 0, status); /* Loop over elements and evaluate response for each. */ element_type_array = oskar_station_element_types_cpu_const(s); num_element_types = oskar_station_num_element_types(s); for (i = 0; i < num_elements; ++i) { int element_type_idx; element_type_idx = element_type_array[i]; if (element_type_idx >= num_element_types) { *status = OSKAR_ERR_OUT_OF_RANGE; break; } oskar_mem_set_alias(element, element_block, i * num_points, num_points, status); oskar_element_evaluate( oskar_station_element_const(s, element_type_idx), element, oskar_station_element_x_alpha_rad(s, i) + M_PI/2.0, /* FIXME Will change: This matches the old convention. */ oskar_station_element_y_alpha_rad(s, i), num_points, x, y, z, frequency_hz, theta, phi, status); } /* Generate beamforming weights. */ oskar_evaluate_element_weights(weights, weights_error, wavenumber, s, beam_x, beam_y, beam_z, time_index, status); /* Use DFT to evaluate array response. */ oskar_dftw(num_elements, wavenumber, oskar_station_element_true_x_enu_metres_const(s), oskar_station_element_true_y_enu_metres_const(s), oskar_station_element_true_z_enu_metres_const(s), weights, num_points, x, y, (is_3d ? z : 0), element_block, beam, status); /* Free element alias. */ oskar_mem_free(element, status); /* Normalise array response if required. */ if (oskar_station_normalise_array_pattern(s)) oskar_mem_scale_real(beam, 1.0 / num_elements, status); } /* Blank (set to zero) points below the horizon. */ oskar_blank_below_horizon(num_points, z, beam, status); } /* If there are child stations, must first evaluate the beam for each. */ else { int i; oskar_Mem* signal; /* Must evaluate array pattern, so check that this is enabled. */ if (!oskar_station_enable_array_pattern(s)) { *status = OSKAR_ERR_SETTINGS_TELESCOPE; return; } /* Get sized work array for this depth, with the correct type. */ signal = oskar_station_work_beam(work, beam, num_elements * num_points, depth, status); /* Check if child stations are identical. */ if (oskar_station_identical_children(s)) { /* Set up the output buffer for the first station. */ oskar_Mem* output0; output0 = oskar_mem_create_alias(signal, 0, num_points, status); /* Recursive call. */ oskar_evaluate_station_beam_aperture_array_private(output0, oskar_station_child_const(s, 0), num_points, x, y, z, gast, frequency_hz, work, time_index, depth + 1, status); /* Copy beam for child station 0 into memory for other stations. */ for (i = 1; i < num_elements; ++i) { oskar_mem_copy_contents(signal, output0, i * num_points, 0, oskar_mem_length(output0), status); } oskar_mem_free(output0, status); } else { /* Loop over child stations. */ for (i = 0; i < num_elements; ++i) { /* Set up the output buffer for this station. */ oskar_Mem* output; output = oskar_mem_create_alias(signal, i * num_points, num_points, status); /* Recursive call. */ oskar_evaluate_station_beam_aperture_array_private(output, oskar_station_child_const(s, i), num_points, x, y, z, gast, frequency_hz, work, time_index, depth + 1, status); oskar_mem_free(output, status); } } /* Generate beamforming weights and form beam from child stations. */ oskar_evaluate_element_weights(weights, weights_error, wavenumber, s, beam_x, beam_y, beam_z, time_index, status); oskar_dftw(num_elements, wavenumber, oskar_station_element_true_x_enu_metres_const(s), oskar_station_element_true_y_enu_metres_const(s), oskar_station_element_true_z_enu_metres_const(s), weights, num_points, x, y, (is_3d ? z : 0), signal, beam, status); /* Normalise array response if required. */ if (oskar_station_normalise_array_pattern(s)) oskar_mem_scale_real(beam, 1.0 / num_elements, status); } }
void oskar_evaluate_station_beam(int num_points, int coord_type, oskar_Mem* x, oskar_Mem* y, oskar_Mem* z, double norm_ra_rad, double norm_dec_rad, const oskar_Station* station, oskar_StationWork* work, int time_index, double frequency_hz, double GAST, int offset_out, oskar_Mem* beam, int* status) { oskar_Mem* out; const size_t num_points_orig = (size_t)num_points; if (*status) return; /* Set output beam array to work buffer. */ out = oskar_station_work_beam_out(work, beam, num_points_orig, status); /* Check that the arrays have enough space to add an extra source at the * end (for normalisation). We don't want to reallocate here, since that * will be slow to do each time: must simply ensure that we pass input * arrays that are large enough. * The normalisation doesn't need to happen if the station has an * isotropic beam. */ const int normalise = oskar_station_normalise_final_beam(station) && (oskar_station_type(station) != OSKAR_STATION_TYPE_ISOTROPIC); if (normalise) { /* Increment number of points. */ num_points++; /* Check the input arrays are big enough to hold the new source. */ if ((int)oskar_mem_length(x) < num_points || (int)oskar_mem_length(y) < num_points || (int)oskar_mem_length(z) < num_points) { *status = OSKAR_ERR_DIMENSION_MISMATCH; return; } /* Get the beam direction in the appropriate coordinate system. */ const int bypass = (coord_type != OSKAR_ENU_DIRECTIONS); const double ha0 = GAST + oskar_station_lon_rad(station) - norm_ra_rad; const double lat = oskar_station_lat_rad(station); oskar_convert_relative_directions_to_enu_directions(1, bypass, 0, 1, 0, 0, 0, ha0, norm_dec_rad, lat, num_points - 1, x, y, z, status); } /* Evaluate the station beam for the given directions. */ if (coord_type == OSKAR_ENU_DIRECTIONS) evaluate_station_beam_enu_directions(out, num_points, x, y, z, station, work, time_index, frequency_hz, GAST, status); else if (coord_type == OSKAR_RELATIVE_DIRECTIONS) evaluate_station_beam_relative_directions(out, num_points, x, y, z, station, work, time_index, frequency_hz, GAST, status); else *status = OSKAR_ERR_INVALID_ARGUMENT; /* Scale beam pattern by amplitude at the last source if required. */ if (normalise) oskar_mem_normalise(out, 0, oskar_mem_length(out), num_points - 1, status); /* Copy output beam data. */ oskar_mem_copy_contents(beam, out, offset_out, 0, num_points_orig, status); }
static void* run_blocks(void* arg) { oskar_Imager* h; oskar_Mem *plane, *uu, *vv, *ww = 0, *amp, *weight, *block, *l, *m, *n; size_t max_size; const size_t smallest = 1024, largest = 65536; int dev_loc = OSKAR_CPU, *status; /* Get thread function arguments. */ h = ((ThreadArgs*)arg)->h; const int thread_id = ((ThreadArgs*)arg)->thread_id; const int num_vis = ((ThreadArgs*)arg)->num_vis; plane = ((ThreadArgs*)arg)->plane; status = &(h->status); /* Set the device used by the thread. */ if (thread_id < h->num_gpus) { dev_loc = h->dev_loc; oskar_device_set(h->dev_loc, h->gpu_ids[thread_id], status); } /* Copy visibility data to device. */ uu = oskar_mem_create_copy(((ThreadArgs*)arg)->uu, dev_loc, status); vv = oskar_mem_create_copy(((ThreadArgs*)arg)->vv, dev_loc, status); amp = oskar_mem_create_copy(((ThreadArgs*)arg)->amp, dev_loc, status); weight = oskar_mem_create_copy(((ThreadArgs*)arg)->weight, dev_loc, status); if (h->algorithm == OSKAR_ALGORITHM_DFT_3D) ww = oskar_mem_create_copy(((ThreadArgs*)arg)->ww, dev_loc, status); #ifdef _OPENMP /* Disable nested parallelism. */ omp_set_nested(0); omp_set_num_threads(1); #endif /* Calculate the maximum pixel block size, and number of blocks. */ const size_t num_pixels = (size_t)h->image_size * (size_t)h->image_size; max_size = num_pixels / h->num_devices; max_size = ((max_size + smallest - 1) / smallest) * smallest; if (max_size > largest) max_size = largest; if (max_size < smallest) max_size = smallest; const int num_blocks = (int) ((num_pixels + max_size - 1) / max_size); /* Allocate device memory for pixel block data. */ block = oskar_mem_create(h->imager_prec, dev_loc, 0, status); l = oskar_mem_create(h->imager_prec, dev_loc, max_size, status); m = oskar_mem_create(h->imager_prec, dev_loc, max_size, status); n = oskar_mem_create(h->imager_prec, dev_loc, max_size, status); /* Loop until all blocks are done. */ for (;;) { size_t block_size; /* Get a unique block index. */ oskar_mutex_lock(h->mutex); const int i_block = (h->i_block)++; oskar_mutex_unlock(h->mutex); if ((i_block >= num_blocks) || *status) break; /* Calculate the block size. */ const size_t block_start = i_block * max_size; block_size = num_pixels - block_start; if (block_size > max_size) block_size = max_size; /* Copy the (l,m,n) positions for the block. */ oskar_mem_copy_contents(l, h->l, 0, block_start, block_size, status); oskar_mem_copy_contents(m, h->m, 0, block_start, block_size, status); if (h->algorithm == OSKAR_ALGORITHM_DFT_3D) oskar_mem_copy_contents(n, h->n, 0, block_start, block_size, status); /* Run DFT for the block. */ oskar_dft_c2r(num_vis, 2.0 * M_PI, uu, vv, ww, amp, weight, (int) block_size, l, m, n, block, status); /* Add data to existing pixels. */ oskar_mem_add(plane, plane, block, block_start, block_start, 0, block_size, status); } /* Free memory. */ oskar_mem_free(uu, status); oskar_mem_free(vv, status); oskar_mem_free(ww, status); oskar_mem_free(amp, status); oskar_mem_free(weight, status); oskar_mem_free(block, status); oskar_mem_free(l, status); oskar_mem_free(m, status); oskar_mem_free(n, status); return 0; }
/* 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); }
/* * Translation layer from new file format to old structure. * This will be deleted when the old oskar_Vis structure is fully retired. */ oskar_Vis* oskar_vis_read_new(oskar_Binary* h, int* status) { oskar_VisHeader* hdr = 0; oskar_VisBlock* blk = 0; oskar_Vis* vis = 0; oskar_Mem* amp = 0; const oskar_Mem* xcorr = 0; int amp_type, max_times_per_block, num_channels, num_stations, num_times; int i, num_blocks; double freq_ref_hz, freq_inc_hz, time_ref_mjd_utc, time_inc_sec; /* Try to read the new header. */ hdr = oskar_vis_header_read(h, status); if (*status) { oskar_vis_header_free(hdr, status); return 0; } /* Create the old vis structure. */ amp_type = oskar_vis_header_amp_type(hdr); max_times_per_block = oskar_vis_header_max_times_per_block(hdr); num_channels = oskar_vis_header_num_channels_total(hdr); num_stations = oskar_vis_header_num_stations(hdr); num_times = oskar_vis_header_num_times_total(hdr); vis = oskar_vis_create(amp_type, OSKAR_CPU, num_channels, num_times, num_stations, status); if (*status) { oskar_vis_header_free(hdr, status); oskar_vis_free(vis, status); return 0; } /* Copy station coordinates and metadata. */ freq_ref_hz = oskar_vis_header_freq_start_hz(hdr); freq_inc_hz = oskar_vis_header_freq_inc_hz(hdr); time_ref_mjd_utc = oskar_vis_header_time_start_mjd_utc(hdr); time_inc_sec = oskar_vis_header_time_inc_sec(hdr); oskar_mem_copy(oskar_vis_station_x_offset_ecef_metres(vis), oskar_vis_header_station_x_offset_ecef_metres_const(hdr), status); oskar_mem_copy(oskar_vis_station_y_offset_ecef_metres(vis), oskar_vis_header_station_y_offset_ecef_metres_const(hdr), status); oskar_mem_copy(oskar_vis_station_z_offset_ecef_metres(vis), oskar_vis_header_station_z_offset_ecef_metres_const(hdr), status); oskar_mem_copy(oskar_vis_settings(vis), oskar_vis_header_settings_const(hdr), status); oskar_mem_copy(oskar_vis_telescope_path(vis), oskar_vis_header_telescope_path_const(hdr), status); oskar_vis_set_channel_bandwidth_hz(vis, oskar_vis_header_channel_bandwidth_hz(hdr)); oskar_vis_set_freq_inc_hz(vis, freq_inc_hz); oskar_vis_set_freq_start_hz(vis, freq_ref_hz); oskar_vis_set_phase_centre(vis, oskar_vis_header_phase_centre_ra_deg(hdr), oskar_vis_header_phase_centre_dec_deg(hdr)); oskar_vis_set_telescope_position(vis, oskar_vis_header_telescope_lon_deg(hdr), oskar_vis_header_telescope_lat_deg(hdr), oskar_vis_header_telescope_alt_metres(hdr)); oskar_vis_set_time_average_sec(vis, oskar_vis_header_time_average_sec(hdr)); oskar_vis_set_time_inc_sec(vis, time_inc_sec); oskar_vis_set_time_start_mjd_utc(vis, time_ref_mjd_utc); /* Create a visibility block to read into. */ blk = oskar_vis_block_create_from_header(OSKAR_CPU, hdr, status); amp = oskar_vis_amplitude(vis); xcorr = oskar_vis_block_cross_correlations_const(blk); /* Work out the number of blocks. */ num_blocks = (num_times + max_times_per_block - 1) / max_times_per_block; for (i = 0; i < num_blocks; ++i) { int block_length, num_baselines, time_offset, total_baselines, t, c; /* Read the block. */ oskar_vis_block_read(blk, hdr, h, i, status); num_baselines = oskar_vis_block_num_baselines(blk); block_length = oskar_vis_block_num_times(blk); /* Copy the baseline coordinate data. */ time_offset = i * max_times_per_block * num_baselines; total_baselines = num_baselines * block_length; oskar_mem_copy_contents(oskar_vis_baseline_uu_metres(vis), oskar_vis_block_baseline_uu_metres_const(blk), time_offset, 0, total_baselines, status); oskar_mem_copy_contents(oskar_vis_baseline_vv_metres(vis), oskar_vis_block_baseline_vv_metres_const(blk), time_offset, 0, total_baselines, status); oskar_mem_copy_contents(oskar_vis_baseline_ww_metres(vis), oskar_vis_block_baseline_ww_metres_const(blk), time_offset, 0, total_baselines, status); /* Fill the array in the old dimension order. */ for (t = 0; t < block_length; ++t) { for (c = 0; c < num_channels; ++c) { oskar_mem_copy_contents(amp, xcorr, num_baselines * (c * num_times + i * max_times_per_block + t), num_baselines * (t * num_channels + c), num_baselines, status); } } } /* Clean up and return. */ oskar_vis_block_free(blk, status); oskar_vis_header_free(hdr, status); return vis; }