Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);
    }
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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;
}
Esempio n. 9
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);
}
Esempio n. 10
0
/*
 * 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;
}