예제 #1
0
/* Evaluate the TEC value for each pierce point - note: at the moment this is
 * just the accumulation of one or more TID screens.
 * TODO convert this to a stand-alone function.
 */
static void oskar_evaluate_TEC(oskar_WorkJonesZ* work, int num_pp,
        const oskar_SettingsIonosphere* settings,
        double gast, int* status)
{
    int i;

    /* FIXME(BM) For now limit number of screens to 1, this can be removed
     * if a TEC model which is valid for multiple screens is implemented
     */
    if (settings->num_TID_screens > 1)
        *status = OSKAR_ERR_INVALID_ARGUMENT;

    oskar_mem_set_value_real(work->total_TEC, 0.0, 0, 0, status);

    /* Loop over TID screens to evaluate TEC values */
    for (i = 0; i < settings->num_TID_screens; ++i)
    {
        oskar_mem_set_value_real(work->screen_TEC, 0.0, 0, 0, status);

        /* Evaluate TEC values for the screen */
        oskar_evaluate_tec_tid(work->screen_TEC, num_pp, work->pp_lon,
                work->pp_lat, work->pp_rel_path, settings->TEC0,
                &settings->TID[i], gast);

        /* Accumulate into total TEC */
        /* FIXME(BM) addition is not physical for more than one TEC screen in
         * the way TIDs are currently evaluated as TEC0 is added into both
         * screens.
         */
        oskar_mem_add(work->total_TEC, work->total_TEC, work->screen_TEC,
                oskar_mem_length(work->total_TEC), status);
    }
}
void oskar_sky_set_gaussian_parameters(oskar_Sky* sky,
        double FWHM_major, double FWHM_minor, double position_angle,
        int* status)
{
    /* Check if safe to proceed. */
    if (*status) return;

    oskar_mem_set_value_real(sky->fwhm_major_rad, FWHM_major, 0, 0, status);
    oskar_mem_set_value_real(sky->fwhm_minor_rad, FWHM_minor, 0, 0, status);
    oskar_mem_set_value_real(sky->pa_rad, position_angle, 0, 0, status);
}
예제 #3
0
TEST(element_weights_errors, test_evaluate)
{
    int num_elements           = 10000;
    double element_gain        = 1.0;
    double element_gain_error  = 0.0;
    double element_phase       = 0.0 * M_PI;
    double element_phase_error = 0.0  * M_PI;
    int error = 0;
    unsigned int seed = 1;

    oskar_Mem *d_gain, *d_gain_error, *d_phase, *d_phase_error, *d_errors;
    d_gain = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &error);
    d_gain_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &error);
    d_phase = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &error);
    d_phase_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &error);
    d_errors = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU,
            num_elements, &error);
    ASSERT_EQ(0, error) << oskar_get_error_string(error);

    oskar_mem_set_value_real(d_gain, element_gain, 0, 0, &error);
    oskar_mem_set_value_real(d_gain_error, element_gain_error, 0, 0, &error);
    oskar_mem_set_value_real(d_phase, element_phase, 0, 0, &error);
    oskar_mem_set_value_real(d_phase_error, element_phase_error, 0, 0, &error);
    oskar_mem_set_value_real(d_errors, 0.0, 0, 0, &error);
    ASSERT_EQ(0, error) << oskar_get_error_string(error);

    // Evaluate weights errors.
    oskar_evaluate_element_weights_errors(num_elements,
            d_gain, d_gain_error, d_phase, d_phase_error,
            seed, 0, 0, d_errors, &error);
    ASSERT_EQ(0, error) << oskar_get_error_string(error);

    // Write memory to file for inspection.
    const char* fname = "temp_test_element_errors.dat";
    FILE* file = fopen(fname, "w");
    oskar_mem_save_ascii(file, 5, num_elements, &error,
            d_gain, d_gain_error, d_phase, d_phase_error, d_errors);
    fclose(file);
    remove(fname);

    // Free memory.
    oskar_mem_free(d_gain, &error);
    oskar_mem_free(d_gain_error, &error);
    oskar_mem_free(d_phase, &error);
    oskar_mem_free(d_phase_error, &error);
    oskar_mem_free(d_errors, &error);
    ASSERT_EQ(0, error) << oskar_get_error_string(error);
}
예제 #4
0
void oskar_station_resize(oskar_Station* station, int num_elements,
        int* status)
{
    /* Check if safe to proceed. */
    if (*status) return;

    /* Resize arrays in the model. */
    oskar_mem_realloc(station->element_true_x_enu_metres, num_elements, status);
    oskar_mem_realloc(station->element_true_y_enu_metres, num_elements, status);
    oskar_mem_realloc(station->element_true_z_enu_metres, num_elements, status);
    oskar_mem_realloc(station->element_measured_x_enu_metres,
            num_elements, status);
    oskar_mem_realloc(station->element_measured_y_enu_metres,
            num_elements, status);
    oskar_mem_realloc(station->element_measured_z_enu_metres,
            num_elements, status);
    oskar_mem_realloc(station->element_weight, num_elements, status);
    oskar_mem_realloc(station->element_gain, num_elements, status);
    oskar_mem_realloc(station->element_gain_error, num_elements, status);
    oskar_mem_realloc(station->element_phase_offset_rad, num_elements, status);
    oskar_mem_realloc(station->element_phase_error_rad, num_elements, status);
    oskar_mem_realloc(station->element_x_alpha_cpu, num_elements, status);
    oskar_mem_realloc(station->element_x_beta_cpu, num_elements, status);
    oskar_mem_realloc(station->element_x_gamma_cpu, num_elements, status);
    oskar_mem_realloc(station->element_y_alpha_cpu, num_elements, status);
    oskar_mem_realloc(station->element_y_beta_cpu, num_elements, status);
    oskar_mem_realloc(station->element_y_gamma_cpu, num_elements, status);
    oskar_mem_realloc(station->element_types, num_elements, status);
    oskar_mem_realloc(station->element_types_cpu, num_elements, status);
    oskar_mem_realloc(station->element_mount_types_cpu, num_elements, status);

    /* Initialise any new elements with default values. */
    if (num_elements > station->num_elements)
    {
        int offset, num_new;
        offset = station->num_elements;
        num_new = num_elements - offset;

        /* Must set default element weight, gain and orientation. */
        oskar_mem_set_value_real(station->element_gain,
                1.0, offset, num_new, status);
        oskar_mem_set_value_real(station->element_weight,
                1.0, offset, num_new, status);
        memset(oskar_mem_char(station->element_mount_types_cpu) + offset,
                'F', num_new);
    }

    /* Set the new number of elements. */
    station->num_elements = num_elements;
}
void oskar_station_override_element_time_variable_phases(oskar_Station* s,
        double phase_std, int* status)
{
    int i;

    /* Check if safe to proceed. */
    if (*status) return;

    /* Check if there are child stations. */
    if (oskar_station_has_child(s))
    {
        /* Recursive call to find the last level (i.e. the element data). */
        for (i = 0; i < s->num_elements; ++i)
        {
            oskar_station_override_element_time_variable_phases(
                    oskar_station_child(s, i), phase_std, status);
        }
    }
    else
    {
        /* Override element data at last level. */
        oskar_mem_set_value_real(s->element_phase_error_rad,
                phase_std, 0, 0, status);
    }
}
예제 #6
0
TEST(Mem, set_value_real_double_complex_matrix)
{
    // Double precision complex matrix.
    int n = 100, status = 0;
    oskar_Mem *mem, *mem2;
    mem = oskar_mem_create(OSKAR_DOUBLE_COMPLEX_MATRIX, OSKAR_GPU, n,
            &status);
    oskar_mem_set_value_real(mem, 6.5, 0, 0, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    mem2 = oskar_mem_create_copy(mem, OSKAR_CPU, &status);
    double4c* v = oskar_mem_double4c(mem2, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    for (int i = 0; i < n; ++i)
    {
        EXPECT_DOUBLE_EQ(v[i].a.x, 6.5);
        EXPECT_DOUBLE_EQ(v[i].a.y, 0.0);
        EXPECT_DOUBLE_EQ(v[i].b.x, 0.0);
        EXPECT_DOUBLE_EQ(v[i].b.y, 0.0);
        EXPECT_DOUBLE_EQ(v[i].c.x, 0.0);
        EXPECT_DOUBLE_EQ(v[i].c.y, 0.0);
        EXPECT_DOUBLE_EQ(v[i].d.x, 6.5);
        EXPECT_DOUBLE_EQ(v[i].d.y, 0.0);
    }
    oskar_mem_free(mem, &status);
    oskar_mem_free(mem2, &status);
}
예제 #7
0
static void evaluate_station_beam_enu_directions(oskar_Mem* beam_pattern,
        int np, const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z,
        const oskar_Station* station, oskar_StationWork* work,
        int time_index, double frequency_hz, double GAST, int* status)
{
    if (*status) return;

    switch (oskar_station_type(station))
    {
        case OSKAR_STATION_TYPE_AA:
        {
            oskar_evaluate_station_beam_aperture_array(beam_pattern, station,
                    np, x, y, z, GAST, frequency_hz, work, time_index, status);
            break;
        }
        case OSKAR_STATION_TYPE_ISOTROPIC:
        {
            oskar_mem_set_value_real(beam_pattern, 1.0, 0, np, status);
            break;
        }
        case OSKAR_STATION_TYPE_GAUSSIAN_BEAM:
        {
            oskar_Mem *l, *m, *n; /* Relative direction cosines */
            double fwhm, f0;
            l = oskar_station_work_enu_direction_x(work);
            m = oskar_station_work_enu_direction_y(work);
            n = oskar_station_work_enu_direction_z(work);
            compute_relative_directions(l, m, n, np, x, y, z, station, GAST,
                    status);
            fwhm = oskar_station_gaussian_beam_fwhm_rad(station);
            f0 =oskar_station_gaussian_beam_reference_freq_hz(station);
            fwhm *= f0 / frequency_hz;
            oskar_evaluate_station_beam_gaussian(beam_pattern, np, l, m, z,
                    fwhm, status);
            break;
        }
        case OSKAR_STATION_TYPE_VLA_PBCOR:
        {
            oskar_Mem *l, *m, *n; /* Relative direction cosines */
            l = oskar_station_work_enu_direction_x(work);
            m = oskar_station_work_enu_direction_y(work);
            n = oskar_station_work_enu_direction_z(work);
            compute_relative_directions(l, m, n, np, x, y, z, station, GAST,
                    status);
            oskar_evaluate_vla_beam_pbcor(beam_pattern, np, l, m, frequency_hz,
                    status);
            break;
        }
        default:
        {
            *status = OSKAR_ERR_SETTINGS_TELESCOPE;
            break;
        }
    };
}
예제 #8
0
TEST(Mem, set_value_real_single)
{
    // Single precision real.
    int n = 100, status = 0;
    oskar_Mem *mem;
    mem = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU, n, &status);
    oskar_mem_set_value_real(mem, 4.5, 0, 0, &status);
    float* v = oskar_mem_float(mem, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    for (int i = 0; i < n; ++i)
    {
        EXPECT_FLOAT_EQ(v[i], 4.5);
    }
    oskar_mem_free(mem, &status);
}
예제 #9
0
TEST(Mem, set_value_real_double)
{
    // Double precision real.
    int n = 100, status = 0;
    oskar_Mem *mem;
    mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, n, &status);
    oskar_mem_set_value_real(mem, 4.5, 0, 0, &status);
    double* v = oskar_mem_double(mem, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    for (int i = 0; i < n; ++i)
    {
        EXPECT_DOUBLE_EQ(v[i], 4.5);
    }
    oskar_mem_free(mem, &status);
}
예제 #10
0
TEST(Mem, set_value_real_single_complex)
{
    // Single precision complex.
    int n = 100, status = 0;
    oskar_Mem *mem, *mem2;
    mem = oskar_mem_create(OSKAR_SINGLE_COMPLEX, OSKAR_GPU, n,
            &status);
    oskar_mem_set_value_real(mem, 6.5, 0, 0, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    mem2 = oskar_mem_create_copy(mem, OSKAR_CPU, &status);
    float2* v = oskar_mem_float2(mem2, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    for (int i = 0; i < n; ++i)
    {
        EXPECT_FLOAT_EQ(v[i].x, 6.5);
        EXPECT_FLOAT_EQ(v[i].y, 0.0);
    }
    oskar_mem_free(mem, &status);
    oskar_mem_free(mem2, &status);
}
예제 #11
0
TEST(element_weights_errors, test_reinit)
{
    int num_elements   = 5;
    int status = 0;

    double gain        = 1.5;
    double gain_error  = 0.2;
    double phase       = 0.1 * M_PI;
    double phase_error = (5 / 180.0) * M_PI;

    oskar_Mem *d_errors, *d_gain, *d_gain_error, *d_phase, *d_phase_error;
    d_errors = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU,
            num_elements, &status);
    d_gain = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_gain_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_phase = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_phase_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    oskar_mem_set_value_real(d_gain, gain, 0, 0, &status);
    oskar_mem_set_value_real(d_gain_error, gain_error, 0, 0, &status);
    oskar_mem_set_value_real(d_phase, phase, 0, 0, &status);
    oskar_mem_set_value_real(d_phase_error, phase_error, 0, 0, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    int num_channels = 2;
    int num_chunks = 3;
    int num_stations = 5;
    int num_times = 3;
    unsigned int seed = 1;

    const char* fname = "temp_test_weights_error_reinit.dat";
    FILE* file = fopen(fname, "w");
    for (int chan = 0; chan < num_channels; ++chan)
    {
        fprintf(file, "channel: %i\n", chan);
        for (int chunk = 0; chunk < num_chunks; ++chunk)
        {
            fprintf(file, "  chunk: %i\n", chunk);
            ASSERT_EQ(0, status) << oskar_get_error_string(status);

            for (int t = 0; t < num_times; ++t)
            {
                fprintf(file, "    time: %i\n", t);
                for (int s = 0; s < num_stations; ++s)
                {
                    fprintf(file, "      station: %i  ==> ", s);
                    oskar_evaluate_element_weights_errors(num_elements,
                            d_gain, d_gain_error, d_phase, d_phase_error,
                            seed, t, s, d_errors, &status);
                    ASSERT_EQ(0, status) << oskar_get_error_string(status);
                    oskar_Mem *h_errors = oskar_mem_create_copy(d_errors,
                            OSKAR_CPU, &status);
                    double2* errors = oskar_mem_double2(h_errors, &status);
                    for (int i = 0; i < num_elements; ++i)
                    {
                        fprintf(file, "(% -6.4f, % -6.4f), ",
                                errors[i].x, errors[i].y);
                    }
                    fprintf(file, "\n");
                    oskar_mem_free(h_errors, &status);
                }
            }
            ASSERT_EQ(0, status) << oskar_get_error_string(status);
        }
    }
    fclose(file);
//    remove(fname);

    oskar_mem_free(d_gain, &status);
    oskar_mem_free(d_gain_error, &status);
    oskar_mem_free(d_phase, &status);
    oskar_mem_free(d_phase_error, &status);
    oskar_mem_free(d_errors, &status);
}
예제 #12
0
TEST(element_weights_errors, test_apply)
{
    int num_elements   = 10000;
    int status = 0;

    double gain        = 1.5;
    double gain_error  = 0.2;
    double phase       = 0.1 * M_PI;
    double phase_error = (5 / 180.0) * M_PI;

    double weight_gain  = 1.0;
    double weight_phase = 0.5 * M_PI;

    double2 weight;
    weight.x = weight_gain * cos(weight_phase);
    weight.y = weight_gain * sin(weight_phase);

    oskar_Mem *d_gain, *d_gain_error, *d_phase, *d_phase_error, *d_errors;
    oskar_Mem *h_weights, *d_weights;
    d_errors = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU,
            num_elements, &status);
    d_gain = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_gain_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_phase = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    d_phase_error = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU,
            num_elements, &status);
    h_weights = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU,
            num_elements, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    oskar_mem_set_value_real(d_gain, gain, 0, 0, &status);
    oskar_mem_set_value_real(d_gain_error, gain_error, 0, 0, &status);
    oskar_mem_set_value_real(d_phase, phase, 0, 0, &status);
    oskar_mem_set_value_real(d_phase_error, phase_error, 0, 0, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    double2* h_weights_ = oskar_mem_double2(h_weights, &status);
    for (int i = 0; i < num_elements; ++i)
    {
        h_weights_[i].x = weight.x;
        h_weights_[i].y = weight.y;
    }
    d_weights = oskar_mem_create_copy(h_weights, OSKAR_GPU, &status);

    oskar_evaluate_element_weights_errors(num_elements,
            d_gain, d_gain_error, d_phase, d_phase_error,
            0, 0, 0, d_errors, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    oskar_mem_element_multiply(NULL, d_weights, d_errors, num_elements, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Write memory to file for inspection.
    const char* fname = "temp_test_weights.dat";
    FILE* file = fopen(fname, "w");
    oskar_mem_save_ascii(file, 7, num_elements, &status,
            d_gain, d_gain_error, d_phase, d_phase_error, d_errors,
            h_weights, d_weights);
    fclose(file);
    remove(fname);

    // Free memory.
    oskar_mem_free(d_gain, &status);
    oskar_mem_free(d_gain_error, &status);
    oskar_mem_free(d_phase, &status);
    oskar_mem_free(d_phase_error, &status);
    oskar_mem_free(d_errors, &status);
    oskar_mem_free(h_weights, &status);
    oskar_mem_free(d_weights, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
}
예제 #13
0
void oskar_element_evaluate(
        const oskar_Element* model,
        double orientation_x,
        double orientation_y,
        int offset_points,
        int num_points,
        const oskar_Mem* x,
        const oskar_Mem* y,
        const oskar_Mem* z,
        double frequency_hz,
        oskar_Mem* theta,
        oskar_Mem* phi,
        int offset_out,
        oskar_Mem* output,
        int* status)
{
    double dipole_length_m;
    if (*status) return;
    if (!oskar_mem_is_complex(output))
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }
    oskar_mem_ensure(output, offset_out + num_points, status);
    oskar_mem_ensure(theta, num_points, status);
    oskar_mem_ensure(phi, num_points, status);

    /* Get the element model properties. */
    const int element_type = model->element_type;
    const int taper_type   = model->taper_type;
    const int id = oskar_find_closest_match_d(frequency_hz,
            oskar_element_num_freq(model),
            oskar_element_freqs_hz_const(model));
    dipole_length_m = model->dipole_length;
    if (model->dipole_length_units == OSKAR_WAVELENGTHS)
        dipole_length_m *= (C_0 / frequency_hz);

    /* Compute modified theta and phi coordinates for dipole X. */
    oskar_convert_enu_directions_to_theta_phi(offset_points, num_points,
            x, y, z, (M_PI/2) - orientation_x, theta, phi, status);

    /* Check if element type is isotropic. */
    if (element_type == OSKAR_ELEMENT_TYPE_ISOTROPIC)
        oskar_mem_set_value_real(output, 1.0, offset_out, num_points, status);

    /* Evaluate polarised response if output array is matrix type. */
    if (oskar_mem_is_matrix(output))
    {
        const int offset_out_real = offset_out * 8;
        const int offset_out_cplx = offset_out * 4;
        if (oskar_element_has_x_spherical_wave_data(model, id))
            oskar_evaluate_spherical_wave_sum(num_points, theta, phi,
                    model->x_lmax[id], model->x_te[id], model->x_tm[id],
                    4, offset_out_cplx + 0, output, status);
        else if (oskar_element_has_x_spline_data(model, id))
        {
            oskar_splines_evaluate(model->x_h_re[id], num_points, theta, phi,
                    8, offset_out_real + 0, output, status);
            oskar_splines_evaluate(model->x_h_im[id], num_points, theta, phi,
                    8, offset_out_real + 1, output, status);
            oskar_splines_evaluate(model->x_v_re[id], num_points, theta, phi,
                    8, offset_out_real + 2, output, status);
            oskar_splines_evaluate(model->x_v_im[id], num_points, theta, phi,
                    8, offset_out_real + 3, output, status);
            oskar_convert_ludwig3_to_theta_phi_components(num_points, phi,
                    4, offset_out_cplx + 0, output, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE)
            oskar_evaluate_dipole_pattern(num_points, theta, phi,
                    frequency_hz, dipole_length_m,
                    4, offset_out_cplx + 0, output, status);
        else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE)
            oskar_evaluate_geometric_dipole_pattern(num_points, theta, phi,
                    4, offset_out_cplx + 0, output, status);

        /* Compute modified theta and phi coordinates for dipole Y. */
        oskar_convert_enu_directions_to_theta_phi(offset_points, num_points,
                x, y, z, (M_PI/2) - orientation_y, theta, phi, status);

        if (oskar_element_has_y_spherical_wave_data(model, id))
            oskar_evaluate_spherical_wave_sum(num_points, theta, phi,
                    model->y_lmax[id], model->y_te[id], model->y_tm[id],
                    4, offset_out_cplx + 2, output, status);
        else if (oskar_element_has_y_spline_data(model, id))
        {
            oskar_splines_evaluate(model->y_h_re[id], num_points, theta, phi,
                    8, offset_out_real + 4, output, status);
            oskar_splines_evaluate(model->y_h_im[id], num_points, theta, phi,
                    8, offset_out_real + 5, output, status);
            oskar_splines_evaluate(model->y_v_re[id], num_points, theta, phi,
                    8, offset_out_real + 6, output, status);
            oskar_splines_evaluate(model->y_v_im[id], num_points, theta, phi,
                    8, offset_out_real + 7, output, status);
            oskar_convert_ludwig3_to_theta_phi_components(num_points, phi,
                    4, offset_out_cplx + 2, output, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE)
            oskar_evaluate_dipole_pattern(num_points, theta, phi,
                    frequency_hz, dipole_length_m,
                    4, offset_out_cplx + 2, output, status);
        else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE)
            oskar_evaluate_geometric_dipole_pattern(num_points, theta, phi,
                    4, offset_out_cplx + 2, output, status);
    }
    else /* Scalar response. */
    {
        const int offset_out_real = offset_out * 2;
        if (oskar_element_has_scalar_spline_data(model, id))
        {
            oskar_splines_evaluate(model->scalar_re[id], num_points, theta, phi,
                    2, offset_out_real + 0, output, status);
            oskar_splines_evaluate(model->scalar_im[id], num_points, theta, phi,
                    2, offset_out_real + 1, output, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE)
            oskar_evaluate_dipole_pattern(num_points, theta, phi,
                    frequency_hz, dipole_length_m,
                    1, offset_out, output, status);
        else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE)
            oskar_evaluate_geometric_dipole_pattern(num_points, theta, phi,
                    1, offset_out, output, status);
    }

    /* Apply element tapering, if specified. */
    if (taper_type == OSKAR_ELEMENT_TAPER_COSINE)
        oskar_apply_element_taper_cosine(num_points,
                model->cosine_power, theta, offset_out, output, status);
    else if (taper_type == OSKAR_ELEMENT_TAPER_GAUSSIAN)
        oskar_apply_element_taper_gaussian(num_points,
                model->gaussian_fwhm_rad, theta, offset_out, output, status);
}
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);
}
void oskar_element_evaluate(const oskar_Element* model, oskar_Mem* output,
        double orientation_x, double orientation_y, int num_points,
        const oskar_Mem* x, const oskar_Mem* y, const oskar_Mem* z,
        double frequency_hz, oskar_Mem* theta, oskar_Mem* phi, int* status)
{
    int element_type, taper_type, freq_id;
    double dipole_length_m;

    /* Check if safe to proceed. */
    if (*status) return;

    /* Check that the output array is complex. */
    if (!oskar_mem_is_complex(output))
    {
        *status = OSKAR_ERR_BAD_DATA_TYPE;
        return;
    }

    /* Resize output array if required. */
    if ((int)oskar_mem_length(output) < num_points)
        oskar_mem_realloc(output, num_points, status);

    /* Get the element model properties. */
    element_type    = model->element_type;
    taper_type      = model->taper_type;
    dipole_length_m = model->dipole_length;
    if (model->dipole_length_units == OSKAR_WAVELENGTHS)
        dipole_length_m *= (C_0 / frequency_hz);

    /* Check if element type is isotropic. */
    if (element_type == OSKAR_ELEMENT_TYPE_ISOTROPIC)
        oskar_mem_set_value_real(output, 1.0, 0, 0, status);

    /* Ensure there is enough space in the theta and phi work arrays. */
    if ((int)oskar_mem_length(theta) < num_points)
        oskar_mem_realloc(theta, num_points, status);
    if ((int)oskar_mem_length(phi) < num_points)
        oskar_mem_realloc(phi, num_points, status);

    /* Compute modified theta and phi coordinates for dipole X. */
    oskar_convert_enu_directions_to_theta_phi(num_points, x, y, z,
            M_PI_2 - orientation_x, theta, phi, status);

    /* Evaluate polarised response if output array is matrix type. */
    if (oskar_mem_is_matrix(output))
    {
        /* Check if spline data present for dipole X. */
        if (oskar_element_has_x_spline_data(model))
        {
            /* Get the frequency index. */
            freq_id = oskar_find_closest_match_d(frequency_hz,
                    oskar_element_num_freq(model),
                    oskar_element_freqs_hz_const(model));

            /* Evaluate spline pattern for dipole X. */
            oskar_splines_evaluate(output, 0, 8, model->x_h_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 1, 8, model->x_h_im[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 2, 8, model->x_v_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 3, 8, model->x_v_im[freq_id],
                    num_points, theta, phi, status);

            /* Convert from Ludwig-3 to spherical representation. */
            oskar_convert_ludwig3_to_theta_phi_components(output, 0, 4,
                    num_points, phi, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE)
        {
            /* Evaluate dipole pattern for dipole X. */
            oskar_evaluate_dipole_pattern(output, num_points, theta, phi,
                    frequency_hz, dipole_length_m, 0, 4, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE)
        {
            /* Evaluate dipole pattern for dipole X. */
            oskar_evaluate_geometric_dipole_pattern(output, num_points,
                    theta, phi, 0, 4, status);
        }

        /* Compute modified theta and phi coordinates for dipole Y. */
        oskar_convert_enu_directions_to_theta_phi(num_points, x, y, z,
                M_PI_2 - orientation_y, theta, phi, status);

        /* Check if spline data present for dipole Y. */
        if (oskar_element_has_y_spline_data(model))
        {
            /* Get the frequency index. */
            freq_id = oskar_find_closest_match_d(frequency_hz,
                    oskar_element_num_freq(model),
                    oskar_element_freqs_hz_const(model));

            /* Evaluate spline pattern for dipole Y. */
            oskar_splines_evaluate(output, 4, 8, model->y_h_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 5, 8, model->y_h_im[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 6, 8, model->y_v_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 7, 8, model->y_v_im[freq_id],
                    num_points, theta, phi, status);

            /* Convert from Ludwig-3 to spherical representation. */
            oskar_convert_ludwig3_to_theta_phi_components(output, 2, 4,
                    num_points, phi, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE)
        {
            /* Evaluate dipole pattern for dipole Y. */
            oskar_evaluate_dipole_pattern(output, num_points, theta, phi,
                    frequency_hz, dipole_length_m, 2, 4, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE)
        {
            /* Evaluate dipole pattern for dipole Y. */
            oskar_evaluate_geometric_dipole_pattern(output, num_points,
                    theta, phi, 2, 4, status);
        }
    }

    /* Scalar response. */
    else
    {
        /* Check if scalar spline data present. */
        if (oskar_element_has_scalar_spline_data(model))
        {
            /* Get the frequency index. */
            freq_id = oskar_find_closest_match_d(frequency_hz,
                    oskar_element_num_freq(model),
                    oskar_element_freqs_hz_const(model));

            oskar_splines_evaluate(output, 0, 2, model->scalar_re[freq_id],
                    num_points, theta, phi, status);
            oskar_splines_evaluate(output, 1, 2, model->scalar_im[freq_id],
                    num_points, theta, phi, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_DIPOLE)
        {
            oskar_evaluate_dipole_pattern(output, num_points, theta, phi,
                    frequency_hz, dipole_length_m, 0, 1, status);
        }
        else if (element_type == OSKAR_ELEMENT_TYPE_GEOMETRIC_DIPOLE)
        {
            oskar_evaluate_geometric_dipole_pattern(output, num_points,
                    theta, phi, 0, 1, status);
        }
    }

    /* Apply element tapering, if specified. */
    if (taper_type == OSKAR_ELEMENT_TAPER_COSINE)
    {
        oskar_apply_element_taper_cosine(output, num_points,
                model->cosine_power, theta, status);
    }
    else if (taper_type == OSKAR_ELEMENT_TAPER_GAUSSIAN)
    {
        oskar_apply_element_taper_gaussian(output, num_points,
                model->gaussian_fwhm_rad, theta, status);
    }
}
예제 #16
0
TEST(imager, grid_sum)
{
    int status = 0, type = OSKAR_DOUBLE;
    int size = 2048, grid_size = size * size;

    // Create and set up the imager.
    oskar_Imager* im = oskar_imager_create(type, &status);
    oskar_imager_set_grid_kernel(im, "pillbox", 1, 1, &status);
    oskar_imager_set_fov(im, 5.0);
    oskar_imager_set_size(im, size, &status);
    oskar_Mem* grid = oskar_mem_create(type | OSKAR_COMPLEX, OSKAR_CPU,
            grid_size, &status);
    ASSERT_EQ(0, status);

    // Create visibility data.
    int num_vis = 10000;
    oskar_Mem* uu = oskar_mem_create(type, OSKAR_CPU, num_vis, &status);
    oskar_Mem* vv = oskar_mem_create(type, OSKAR_CPU, num_vis, &status);
    oskar_Mem* ww = oskar_mem_create(type, OSKAR_CPU, num_vis, &status);
    oskar_Mem* vis = oskar_mem_create(type | OSKAR_COMPLEX, OSKAR_CPU, num_vis,
            &status);
    oskar_Mem* weight = oskar_mem_create(type, OSKAR_CPU, num_vis, &status);
    oskar_mem_random_gaussian(uu, 0, 1, 2, 3, 100.0, &status);
    oskar_mem_random_gaussian(vv, 4, 5, 6, 7, 100.0, &status);
    oskar_mem_set_value_real(vis, 1.0, 0, num_vis, &status);
    oskar_mem_set_value_real(weight, 1.0, 0, num_vis, &status);

    // Grid visibility data.
    double plane_norm = 0.0;
    oskar_imager_update_plane(im, num_vis, uu, vv, ww, vis, weight, grid,
            &plane_norm, 0, &status);
    ASSERT_DOUBLE_EQ((double)num_vis, plane_norm);

    // Sum the grid.
    double2* t = oskar_mem_double2(grid, &status);
    double sum = 0.0;
    for (int i = 0; i < grid_size; i++) sum += t[i].x;
    ASSERT_DOUBLE_EQ((double)num_vis, sum);

    // Finalise the image.
    oskar_imager_finalise_plane(im, grid, plane_norm, &status);
    ASSERT_EQ(0, status);

#ifdef WRITE_FITS
    // Get the real part only.
    if (oskar_mem_precision(grid) == OSKAR_DOUBLE)
    {
        double *t = oskar_mem_double(grid, &status);
        for (int j = 0; j < grid_size; ++j) t[j] = t[2 * j];
    }
    else
    {
        float *t = oskar_mem_float(grid, &status);
        for (int j = 0; j < grid_size; ++j) t[j] = t[2 * j];
    }

    // Save the real part.
    fitsfile* f;
    long naxes[2] = {size, size}, firstpix[2] = {1, 1};
    fits_create_file(&f, "test_imager_grid_sum.fits", &status);
    fits_create_img(f, (type == OSKAR_DOUBLE ? DOUBLE_IMG : FLOAT_IMG),
            2, naxes, &status);
    fits_write_pix(f, (type == OSKAR_DOUBLE ? TDOUBLE : TFLOAT),
            firstpix, grid_size, oskar_mem_void(grid), &status);
    fits_close_file(f, &status);
#endif

    // Clean up.
    oskar_imager_free(im, &status);
    oskar_mem_free(uu, &status);
    oskar_mem_free(vv, &status);
    oskar_mem_free(ww, &status);
    oskar_mem_free(vis, &status);
    oskar_mem_free(weight, &status);
    oskar_mem_free(grid, &status);
}
void oskar_evaluate_tec_tid(oskar_Mem* tec, int num_directions,
        const oskar_Mem* lon, const oskar_Mem* lat,
        const oskar_Mem* rel_path_length, double TEC0,
        oskar_SettingsTIDscreen* TID, double gast)
{
    int i, j, type;
    double pp_lon, pp_lat;
    double pp_sec;
    double pp_tec;
    double amp, w, th, v; /* TID parameters */
    double time;
    double earth_radius = 6365.0; /* km -- FIXME */
    int status = 0;

    /* TODO check types, dimensions etc of memory */
    type = oskar_mem_type(tec);

    oskar_mem_set_value_real(tec, 0.0, 0, 0, &status);

    /* Loop over TIDs */
    for (i = 0; i < TID->num_components; ++i)
    {
        amp = TID->amp[i];
        /* convert from km to rads */
        w = TID->wavelength[i] / (earth_radius + TID->height_km);
        th = TID->theta[i] * M_PI/180.;
        /* convert from km/h to rad/s */
        v = (TID->speed[i]/(earth_radius + TID->height_km)) / 3600;

        time = gast * 86400.0; /* days->sec */

        /* Loop over directions */
        for (j = 0; j < num_directions; ++j)
        {
            if (type == OSKAR_DOUBLE)
            {
                pp_lon = oskar_mem_double_const(lon, &status)[j];
                pp_lat = oskar_mem_double_const(lat, &status)[j];
                pp_sec = oskar_mem_double_const(rel_path_length, &status)[j];
                pp_tec = pp_sec * amp * TEC0 * (
                        cos( (2.0*M_PI/w) * (cos(th)*pp_lon - v*time) ) +
                        cos( (2.0*M_PI/w) * (sin(th)*pp_lat - v*time) )
                        );
                pp_tec += TEC0;
                oskar_mem_double(tec, &status)[j] += pp_tec;
            }
            else
            {
                pp_lon = (double)oskar_mem_float_const(lon, &status)[j];
                pp_lat = (double)oskar_mem_float_const(lat, &status)[j];
                pp_sec = (double)oskar_mem_float_const(rel_path_length, &status)[j];
                pp_tec = pp_sec * amp * TEC0 * (
                        cos( (2.0*M_PI/w) * (cos(th)*pp_lon - v*time) ) +
                        cos( (2.0*M_PI/w) * (sin(th)*pp_lat - v*time) )
                );
                pp_tec += TEC0;
                oskar_mem_float(tec, &status)[j] += (float)pp_tec;
            }
        } /* loop over directions */
    } /* loop over components. */
}