Beispiel #1
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);
}
TEST(Mem, type_check_double_complex)
{
    int status = 0;
    oskar_Mem *mem;
    mem = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU, 0,
            &status);
    EXPECT_EQ((int)OSKAR_TRUE, oskar_mem_is_double(mem));
    EXPECT_EQ((int)OSKAR_TRUE, oskar_mem_is_complex(mem));
    EXPECT_EQ((int)OSKAR_TRUE, oskar_mem_is_scalar(mem));
    EXPECT_EQ((int)OSKAR_TRUE, oskar_type_is_double(OSKAR_DOUBLE_COMPLEX));
    EXPECT_EQ((int)OSKAR_TRUE, oskar_type_is_complex(OSKAR_DOUBLE_COMPLEX));
    EXPECT_EQ((int)OSKAR_TRUE, oskar_type_is_scalar(OSKAR_DOUBLE_COMPLEX));
    oskar_mem_free(mem, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
}
Beispiel #3
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);
}
Beispiel #4
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);
}
int main(int argc, char** argv)
{
    int error = 0;

    oskar::OptionParser opt("oskar_fits_image_to_sky_model",
            oskar_version_string());
    opt.set_description("Converts a FITS image to an OSKAR sky model. A number "
            "of options are provided to control how much of the image is used "
            "to make the sky model.");
    opt.add_required("FITS file", "The input FITS image to convert.");
    opt.add_required("sky model file", "The output OSKAR sky model file name to save.");
    opt.add_flag("-s", "Spectral index. This is the spectral index that will "
            "be given to each pixel in the output sky model.", 1, "0.0");
    opt.add_flag("-f", "Minimum allowed fraction of image peak. Pixel values "
            "below this fraction will be ignored.", 1, "0.0");
    opt.add_flag("-n", "Noise floor in units of original image. "
            "Pixels below this value will be ignored.", 1, "0.0");
    if (!opt.check_options(argc, argv)) return EXIT_FAILURE;

    // Parse command line.
    double spectral_index = 0.0;
    double min_peak_fraction = 0.0;
    double min_abs_val = 0.0;
    opt.get("-f")->getDouble(min_peak_fraction);
    opt.get("-n")->getDouble(min_abs_val);
    opt.get("-s")->getDouble(spectral_index);

    // Load the FITS image data.
    oskar_Sky* sky = oskar_sky_from_fits_file(OSKAR_DOUBLE, opt.get_arg(0),
            min_peak_fraction, min_abs_val, "Jy/beam", 0, 0.0, spectral_index,
            &error);

    // Write out the sky model.
    oskar_sky_save(opt.get_arg(1), sky, &error);
    if (error)
    {
        oskar_log_error(0, oskar_get_error_string(error));
        return error;
    }

    oskar_sky_free(sky, &error);
    return 0;
}
Beispiel #6
0
static void check_values(const oskar_Mem* approx, const oskar_Mem* accurate)
{
    int status = 0;
    double min_rel_error, max_rel_error, avg_rel_error, std_rel_error, tol;
    oskar_mem_evaluate_relative_error(approx, accurate, &min_rel_error,
            &max_rel_error, &avg_rel_error, &std_rel_error, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    tol = oskar_mem_is_double(approx) &&
            oskar_mem_is_double(accurate) ? 1e-11 : 2e-3;
    EXPECT_LT(max_rel_error, tol) << std::setprecision(5) <<
            "RELATIVE ERROR" <<
            " MIN: " << min_rel_error << " MAX: " << max_rel_error <<
            " AVG: " << avg_rel_error << " STD: " << std_rel_error;
    tol = oskar_mem_is_double(approx) &&
            oskar_mem_is_double(accurate) ? 1e-12 : 1e-5;
    EXPECT_LT(avg_rel_error, tol) << std::setprecision(5) <<
            "RELATIVE ERROR" <<
            " MIN: " << min_rel_error << " MAX: " << max_rel_error <<
            " AVG: " << avg_rel_error << " STD: " << std_rel_error;
}
Beispiel #7
0
static PyObject* load(PyObject* self, PyObject* args)
{
    oskar_Sky* h = 0;
    PyObject* capsule = 0;
    int status = 0, prec = 0;
    const char *filename = 0, *type = 0;
    if (!PyArg_ParseTuple(args, "ss", &filename, &type)) return 0;
    prec = (type[0] == 'S' || type[0] == 's') ? OSKAR_SINGLE : OSKAR_DOUBLE;
    h = oskar_sky_load(filename, prec, &status);
    capsule = PyCapsule_New((void*)h, name, (PyCapsule_Destructor)sky_free);

    /* Check for errors. */
    if (status)
    {
        PyErr_Format(PyExc_RuntimeError,
                "oskar_sky_load() failed with code %d (%s).",
                status, oskar_get_error_string(status));
        return 0;
    }
    return Py_BuildValue("N", capsule); /* Don't increment refcount. */
}
Beispiel #8
0
static PyObject* save(PyObject* self, PyObject* args)
{
    oskar_Sky *h = 0;
    PyObject* capsule = 0;
    int status = 0;
    const char* filename = 0;
    if (!PyArg_ParseTuple(args, "Os", &capsule, &filename)) return 0;
    if (!(h = get_handle(capsule))) return 0;

    /* Save the sky model. */
    oskar_sky_save(filename, h, &status);

    /* Check for errors. */
    if (status)
    {
        PyErr_Format(PyExc_RuntimeError,
                "oskar_sky_save() failed with code %d (%s).",
                status, oskar_get_error_string(status));
        return 0;
    }
    return Py_BuildValue("");
}
int main(int argc, char** argv)
{
    oskar::OptionParser opt("oskar_cuda_system_info", oskar_version_string());
    opt.set_description("Display a summary of the available CUDA capability");
    if (!opt.check_options(argc, argv)) return EXIT_FAILURE;

    // Create the CUDA info structure.
    int error = 0;
    oskar_CudaInfo* info = oskar_cuda_info_create(&error);
    if (error)
    {
        oskar_log_error(0, "Could not determine CUDA system information (%s)",
                oskar_get_error_string(error));
        oskar_cuda_info_free(info);
        return error;
    }

    // Log the CUDA system info.
    oskar_cuda_info_log(NULL, info);
    oskar_cuda_info_free(info);
    return 0;
}
Beispiel #10
0
static PyObject* append(PyObject* self, PyObject* args)
{
    oskar_Sky *h1 = 0, *h2 = 0;
    PyObject *capsule1 = 0, *capsule2 = 0;
    int status = 0;
    if (!PyArg_ParseTuple(args, "OO", &capsule1, &capsule2)) return 0;
    if (!(h1 = get_handle(capsule1))) return 0;
    if (!(h2 = get_handle(capsule2))) return 0;

    /* Append the sky model. */
    oskar_sky_append(h1, h2, &status);

    /* Check for errors. */
    if (status)
    {
        PyErr_Format(PyExc_RuntimeError,
                "oskar_sky_append() failed with code %d (%s).",
                status, oskar_get_error_string(status));
        return 0;
    }
    return Py_BuildValue("");
}
Beispiel #11
0
static PyObject* create_copy(PyObject* self, PyObject* args)
{
    oskar_Sky *h = 0, *t = 0;
    PyObject* capsule = 0;
    int status = 0;
    if (!PyArg_ParseTuple(args, "O", &capsule)) return 0;
    if (!(h = get_handle(capsule))) return 0;
    t = oskar_sky_create_copy(h, OSKAR_CPU, &status);

    /* Check for errors. */
    if (status || !t)
    {
        PyErr_Format(PyExc_RuntimeError,
                "oskar_sky_create_copy() failed with code %d (%s).",
                status, oskar_get_error_string(status));
        oskar_sky_free(t, &status);
        return 0;
    }

    capsule = PyCapsule_New((void*)t, name, (PyCapsule_Destructor)sky_free);
    return Py_BuildValue("N", capsule); /* Don't increment refcount. */
}
Beispiel #12
0
static PyObject* filter_by_flux(PyObject* self, PyObject* args)
{
    oskar_Sky *h = 0;
    PyObject* capsule = 0;
    int status = 0;
    double min_flux_jy = 0.0, max_flux_jy = 0.0;
    if (!PyArg_ParseTuple(args, "Odd", &capsule, &min_flux_jy, &max_flux_jy))
        return 0;
    if (!(h = get_handle(capsule))) return 0;

    /* Filter the sky model. */
    oskar_sky_filter_by_flux(h, min_flux_jy, max_flux_jy, &status);

    /* Check for errors. */
    if (status)
    {
        PyErr_Format(PyExc_RuntimeError,
                "oskar_sky_filter_by_flux() failed with code %d (%s).",
                status, oskar_get_error_string(status));
        return 0;
    }
    return Py_BuildValue("");
}
Beispiel #13
0
static PyObject* append_file(PyObject* self, PyObject* args)
{
    oskar_Sky *h = 0, *t = 0;
    PyObject* capsule = 0;
    int status = 0;
    const char* filename = 0;
    if (!PyArg_ParseTuple(args, "Os", &capsule, &filename)) return 0;
    if (!(h = get_handle(capsule))) return 0;

    /* Load the sky model. */
    t = oskar_sky_load(filename, oskar_sky_precision(h), &status);
    oskar_sky_append(h, t, &status);
    oskar_sky_free(t, &status);

    /* Check for errors. */
    if (status)
    {
        PyErr_Format(PyExc_RuntimeError,
                "oskar_sky_load() failed with code %d (%s).",
                status, oskar_get_error_string(status));
        return 0;
    }
    return Py_BuildValue("");
}
Beispiel #14
0
TEST(binary_file, binary_read_write_mem)
{
    const char filename[] = "temp_test_mem_binary.dat";
    int num_cpu = 1000;
    int num_gpu = 2048;
    int status = 0;

    // Create the handle.
    oskar_Binary* h = oskar_binary_create(filename, 'w', &status);

    // Save data from CPU.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU,
                num_cpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        float* data = oskar_mem_float(mem, &status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 1024.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "USER", "TEST", 987654, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_mem_free(mem, &status);
    }

    // Save data from GPU.
    {
        oskar_Mem *mem_cpu, *mem_gpu;
        mem_cpu = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU,
                num_gpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        double2* data = oskar_mem_double2(mem_cpu, &status);

        // Fill array with data.
        for (int i = 0; i < num_gpu; ++i)
        {
            data[i].x = i * 10.0;
            data[i].y = i * 20.0 + 1.0;
        }

        // Copy data to GPU.
        mem_gpu = oskar_mem_create_copy(mem_cpu, OSKAR_GPU, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Save GPU data.
        oskar_binary_write_mem_ext(h, mem_gpu, "AA", "BB", 2, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_mem_free(mem_cpu, &status);
        oskar_mem_free(mem_gpu, &status);
    }

    // Save a single integer with a large index.
    int val = 0xFFFFFF;
    oskar_binary_write_int(h, 50, 9, 800000, val, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Save data from CPU with blank tags.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU,
                num_cpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        double* data = oskar_mem_double(mem, &status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 500.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "", "", 10, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 501.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "", "", 11, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_mem_free(mem, &status);
    }

    // Save CPU data with tags that are equal lengths.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU,
                num_cpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        double* data = oskar_mem_double(mem, &status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 1001.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "DOG", "CAT", 0, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Fill array with data.
        for (int i = 0; i < num_cpu; ++i)
        {
            data[i] = i * 127.0;
        }

        // Save CPU data.
        oskar_binary_write_mem_ext(h, mem, "ONE", "TWO", 0, 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_mem_free(mem, &status);
    }

    // Create the handle for reading.
    oskar_binary_free(h);
    h = oskar_binary_create(filename, 'r', &status);

    // Load data directly to GPU.
    {
        oskar_Mem *mem_gpu, *mem_cpu;
        mem_gpu = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU,
                0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem_gpu, "AA", "BB", 2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        EXPECT_EQ(num_gpu, (int)oskar_mem_length(mem_gpu));

        // Copy back to CPU and examine contents.
        mem_cpu = oskar_mem_create_copy(mem_gpu, OSKAR_CPU, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        double2* data = oskar_mem_double2(mem_cpu, &status);
        for (int i = 0; i < num_gpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 10.0,       data[i].x);
            EXPECT_DOUBLE_EQ(i * 20.0 + 1.0, data[i].y);
        }
        oskar_mem_free(mem_cpu, &status);
        oskar_mem_free(mem_gpu, &status);
    }

    // Load integer with a large index.
    int new_val = 0;
    oskar_binary_read_int(h, 50, 9, 800000, &new_val, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    EXPECT_EQ(val, new_val);

    // Load CPU data.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU,
                num_cpu, &status);
        oskar_binary_read_mem_ext(h, mem, "USER", "TEST", 987654, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        float* data = oskar_mem_float(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 1024.0, data[i]);
        }
        oskar_mem_free(mem, &status);
    }

    // Load CPU data with blank tags.
    {
        double* data;
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU,
                num_cpu, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem, "", "", 10, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem, "DOESN'T", "EXIST", 10, &status);
        EXPECT_EQ((int)OSKAR_ERR_BINARY_TAG_NOT_FOUND, status);
        status = 0;
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        data = oskar_mem_double(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 500.0, data[i]);
        }
        oskar_binary_read_mem_ext(h, mem, "", "", 11, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        data = oskar_mem_double(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 501.0, data[i]);
        }
        oskar_mem_free(mem, &status);
    }

    // Load CPU data with tags that are equal lengths.
    {
        double* data;
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0,
                &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem, "ONE", "TWO", 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        data = oskar_mem_double(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 127.0, data[i]);
        }
        oskar_binary_read_mem_ext(h, mem, "DOG", "CAT", 0, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        ASSERT_EQ(num_cpu, (int)oskar_mem_length(mem));
        data = oskar_mem_double(mem, &status);
        for (int i = 0; i < num_cpu; ++i)
        {
            EXPECT_DOUBLE_EQ(i * 1001.0, data[i]);
        }
        oskar_mem_free(mem, &status);
    }

    // Try to load data that isn't present.
    {
        oskar_Mem* mem = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0,
                &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_binary_read_mem_ext(h, mem, "DOESN'T", "EXIST", 10, &status);
        EXPECT_EQ((int)OSKAR_ERR_BINARY_TAG_NOT_FOUND, status);
        status = 0;
        EXPECT_EQ(0, (int)oskar_mem_length(mem));
        oskar_mem_free(mem, &status);
    }

    // Release the handle.
    oskar_binary_free(h);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
}
TEST(evaluate_baselines, cpu_gpu)
{
    oskar_Mem *u, *v, *w, *uu, *vv, *ww;
    oskar_Mem *u_gpu, *v_gpu, *w_gpu, *uu_gpu, *vv_gpu, *ww_gpu;
    int num_baselines, num_stations = 50, status = 0, type, location;
    double *u_, *v_, *w_, *uu_, *vv_, *ww_;

    num_baselines = num_stations * (num_stations - 1) / 2;

    type = OSKAR_DOUBLE;

    // Allocate host memory.
    location = OSKAR_CPU;
    u = oskar_mem_create(type, location, num_stations, &status);
    v = oskar_mem_create(type, location, num_stations, &status);
    w = oskar_mem_create(type, location, num_stations, &status);
    uu = oskar_mem_create(type, location, num_baselines, &status);
    vv = oskar_mem_create(type, location, num_baselines, &status);
    ww = oskar_mem_create(type, location, num_baselines, &status);
    u_ = oskar_mem_double(u, &status);
    v_ = oskar_mem_double(v, &status);
    w_ = oskar_mem_double(w, &status);
    uu_ = oskar_mem_double(uu, &status);
    vv_ = oskar_mem_double(vv, &status);
    ww_ = oskar_mem_double(ww, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Fill station coordinates with test data.
    for (int i = 0; i < num_stations; ++i)
    {
        u_[i] = (double)(i + 1);
        v_[i] = (double)(i + 2);
        w_[i] = (double)(i + 3);
    }

    // Evaluate baseline coordinates on CPU.
    oskar_convert_station_uvw_to_baseline_uvw(num_stations,
            0, u, v, w, 0, uu, vv, ww, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Check results are correct.
    for (int s1 = 0, b = 0; s1 < num_stations; ++s1)
    {
        for (int s2 = s1 + 1; s2 < num_stations; ++s2, ++b)
        {
            EXPECT_DOUBLE_EQ(u_[s2] - u_[s1], uu_[b]);
            EXPECT_DOUBLE_EQ(v_[s2] - v_[s1], vv_[b]);
            EXPECT_DOUBLE_EQ(w_[s2] - w_[s1], ww_[b]);
        }
    }

    // Allocate device memory and copy input data.
#ifdef OSKAR_HAVE_CUDA
    location = OSKAR_GPU;
#endif
    u_gpu = oskar_mem_create_copy(u, location, &status);
    v_gpu = oskar_mem_create_copy(v, location, &status);
    w_gpu = oskar_mem_create_copy(w, location, &status);
    uu_gpu = oskar_mem_create(type, location, num_baselines, &status);
    vv_gpu = oskar_mem_create(type, location, num_baselines, &status);
    ww_gpu = oskar_mem_create(type, location, num_baselines, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Evaluate baseline coordinates on device.
    oskar_convert_station_uvw_to_baseline_uvw(num_stations,
            0, u_gpu, v_gpu, w_gpu, 0, uu_gpu, vv_gpu, ww_gpu, &status);
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Check results are consistent.
    double max_, avg;
    oskar_mem_evaluate_relative_error(uu_gpu, uu, 0, &max_, &avg, 0, &status);
    ASSERT_LT(max_, 1e-12);
    ASSERT_LT(avg, 1e-12);
    oskar_mem_evaluate_relative_error(vv_gpu, vv, 0, &max_, &avg, 0, &status);
    ASSERT_LT(max_, 1e-12);
    ASSERT_LT(avg, 1e-12);
    oskar_mem_evaluate_relative_error(ww_gpu, ww, 0, &max_, &avg, 0, &status);
    ASSERT_LT(max_, 1e-12);
    ASSERT_LT(avg, 1e-12);

    // Free memory.
    oskar_mem_free(u, &status);
    oskar_mem_free(v, &status);
    oskar_mem_free(w, &status);
    oskar_mem_free(uu, &status);
    oskar_mem_free(vv, &status);
    oskar_mem_free(ww, &status);
    oskar_mem_free(u_gpu, &status);
    oskar_mem_free(v_gpu, &status);
    oskar_mem_free(w_gpu, &status);
    oskar_mem_free(uu_gpu, &status);
    oskar_mem_free(vv_gpu, &status);
    oskar_mem_free(ww_gpu, &status);

    ASSERT_EQ(0, status) << oskar_get_error_string(status);
}
Beispiel #16
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);
}
Beispiel #17
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);
}
Beispiel #18
0
TEST(Mem, random_uniform)
{
    int seed = 1;
    int c1 = 437;
    int c2 = 0;
    int c3 = 0xDECAFBAD;
    int n = 544357;
    int status = 0;
    double max_err = 0.0, avg_err = 0.0;
    oskar_Mem* v_cpu_f = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU, n, &status);
    oskar_Mem* v_gpu_f = oskar_mem_create(OSKAR_SINGLE, OSKAR_GPU, n, &status);
    oskar_Mem* v_cpu_d = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, n, &status);
    oskar_Mem* v_gpu_d = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, n, &status);
    oskar_Timer* tmr = oskar_timer_create(OSKAR_TIMER_CUDA);

    // Run in single precision.
    oskar_timer_start(tmr);
    oskar_mem_random_uniform(v_cpu_f, seed, c1, c2, c3, &status);
    report_time(n, "uniform", "single", "CPU", oskar_timer_elapsed(tmr));
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    oskar_timer_start(tmr);
    oskar_mem_random_uniform(v_gpu_f, seed, c1, c2, c3, &status);
    report_time(n, "uniform", "single", "GPU", oskar_timer_elapsed(tmr));
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Check consistency between CPU and GPU results.
    oskar_mem_evaluate_relative_error(v_gpu_f, v_cpu_f, 0,
            &max_err, &avg_err, 0, &status);
    EXPECT_LT(max_err, 1e-5);
    EXPECT_LT(avg_err, 1e-5);

    // Run in double precision.
    oskar_timer_start(tmr);
    oskar_mem_random_uniform(v_cpu_d, seed, c1, c2, c3, &status);
    report_time(n, "uniform", "double", "CPU", oskar_timer_elapsed(tmr));
    ASSERT_EQ(0, status) << oskar_get_error_string(status);
    oskar_timer_start(tmr);
    oskar_mem_random_uniform(v_gpu_d, seed, c1, c2, c3, &status);
    report_time(n, "uniform", "double", "GPU", oskar_timer_elapsed(tmr));
    ASSERT_EQ(0, status) << oskar_get_error_string(status);

    // Check consistency between CPU and GPU results.
    oskar_mem_evaluate_relative_error(v_gpu_d, v_cpu_d, 0,
            &max_err, &avg_err, 0, &status);
    EXPECT_LT(max_err, 1e-10);
    EXPECT_LT(avg_err, 1e-10);

    // Check consistency between single and double precision.
    oskar_mem_evaluate_relative_error(v_cpu_f, v_cpu_d, 0,
            &max_err, &avg_err, 0, &status);
    EXPECT_LT(max_err, 1e-5);
    EXPECT_LT(avg_err, 1e-5);

    if (save)
    {
        FILE* fhan = fopen("random_uniform.txt", "w");
        oskar_mem_save_ascii(fhan, 4, n, &status,
                v_cpu_f, v_gpu_f, v_cpu_d, v_gpu_d);
        fclose(fhan);
    }

    // Free memory.
    oskar_mem_free(v_cpu_f, &status);
    oskar_mem_free(v_gpu_f, &status);
    oskar_mem_free(v_cpu_d, &status);
    oskar_mem_free(v_gpu_d, &status);
    oskar_timer_free(tmr);
}
Beispiel #19
0
int main(int argc, char** argv)
{
    oskar::OptionParser opt("oskar_array_pattern_benchmark", OSKAR_VERSION_STR);
    opt.add_required("No. array elements");
    opt.add_required("No. directions");
    opt.add_flag("-sp", "Use single precision (default: double precision)");
    opt.add_flag("-g", "Run on the GPU");
    opt.add_flag("-c", "Run on the CPU");
    opt.add_flag("-o2c", "Single level beam pattern, phase only (real to complex DFT)");
    opt.add_flag("-c2c", "Beam pattern using complex inputs (complex to complex DFT)");
    opt.add_flag("-m2m", "Beam pattern using complex, polarised inputs (complex matrix to matrix DFT)");
    opt.add_flag("-2d", "Use a 2-dimensional phase term (default: 3D)");
    opt.add_flag("-n", "Number of iterations", 1, "1");
    opt.add_flag("-v", "Display verbose output.");

    if (!opt.check_options(argc, argv))
        return EXIT_FAILURE;

    int num_elements = atoi(opt.get_arg(0));
    int num_directions = atoi(opt.get_arg(1));
    OpType op_type = UNDEF;
    int op_type_count = 0;
    if (opt.is_set("-o2c"))
    {
        op_type = O2C;
        op_type_count++;
    }
    if (opt.is_set("-c2c"))
    {
        op_type = C2C;
        op_type_count++;
    }
    if (opt.is_set("-m2m"))
    {
        op_type = M2M;
        op_type_count++;
    }

    int loc;
    if (opt.is_set("-g"))
        loc = OSKAR_GPU;
    if (opt.is_set("-c"))
        loc = OSKAR_CPU;
    if (!(opt.is_set("-c") ^ opt.is_set("-g")))
    {
        opt.error("Please select one of -g or -c");
        return EXIT_FAILURE;
    }

    int precision = opt.is_set("-sp") ? OSKAR_SINGLE : OSKAR_DOUBLE;
    bool evaluate_2d = opt.is_set("-2d") ? true : false;
    int niter;
    opt.get("-n")->getInt(niter);

    if (op_type == UNDEF || op_type_count != 1) {
        opt.error("Please select one of the following flags: -o2c, -c2c, -m2m");
        return EXIT_FAILURE;
    }

    if (opt.is_set("-v"))
    {
        printf("\n");
        printf("- Number of elements: %i\n", num_elements);
        printf("- Number of directions: %i\n", num_directions);
        printf("- Precision: %s\n", (precision == OSKAR_SINGLE) ? "single" : "double");
        printf("- %s\n", loc == OSKAR_CPU ? "CPU" : "GPU");
        printf("- %s\n", evaluate_2d ? "2D" : "3D");
        printf("- Evaluation type = ");
        if (op_type == O2C) printf("o2c\n");
        else if (op_type == C2C) printf("c2c\n");
        else if (op_type == M2M) printf("m2m\n");
        else printf("Error undefined!\n");
        printf("- Number of iterations: %i\n", niter);
        printf("\n");
    }

    double time_taken = 0.0;
    int status = benchmark(num_elements, num_directions, op_type, loc,
            precision, evaluate_2d, niter, time_taken);

    if (status) {
        fprintf(stderr, "ERROR: array pattern evaluation failed with code %i: "
                "%s\n", status, oskar_get_error_string(status));
        return EXIT_FAILURE;
    }
    if (opt.is_set("-v"))
    {
        printf("==> Total time taken: %f seconds.\n", time_taken);
        printf("==> Time taken per iteration: %f seconds.\n", time_taken/niter);
        printf("\n");
    }
    else {
        printf("%f\n", time_taken/niter);
    }

    return EXIT_SUCCESS;
}
 void destroyTestData()
 {
     int status = 0;
     oskar_mem_free(jones, &status);
     ASSERT_EQ(0, status) << oskar_get_error_string(status);
 }
int main(int argc, char** argv)
{
    int status = 0;
    oskar::OptionParser opt("oskar_evaulate_pierce_points",
            oskar_version_string());
    opt.add_required("settings file");
    if (!opt.check_options(argc, argv)) return EXIT_FAILURE;

    const char* settings_file = opt.get_arg();

    // Create the log.
    oskar_Log* log = oskar_log_create(OSKAR_LOG_MESSAGE, OSKAR_LOG_STATUS);
    oskar_log_message(log, 'M', 0, "Running binary %s", argv[0]);

    // Enum values used in writing time-freq data binary files
    enum OSKAR_TIME_FREQ_TAGS
    {
        TIME_IDX       = 0,
        FREQ_IDX       = 1,
        TIME_MJD_UTC   = 2,
        FREQ_HZ        = 3,
        NUM_FIELDS     = 4,
        NUM_FIELD_TAGS = 5,
        HEADER_OFFSET  = 10,
        DATA           = 0,
        DIMS           = 1,
        LABEL          = 2,
        UNITS          = 3,
        GRP            = OSKAR_TAG_GROUP_TIME_FREQ_DATA
    };

    oskar_Settings_old settings;
    oskar_settings_old_load(&settings, log, settings_file, &status);
    oskar_log_set_keep_file(log, settings.sim.keep_log_file);
    if (status) return status;

    oskar_Telescope* tel = oskar_settings_to_telescope(&settings, log, &status);
    oskar_Sky* sky = oskar_settings_to_sky(&settings, log, &status);

    // FIXME remove this restriction ... (see evaluate Z)
    if (settings.ionosphere.num_TID_screens != 1)
        return OSKAR_ERR_SETUP_FAIL;

    int type = settings.sim.double_precision ? OSKAR_DOUBLE : OSKAR_SINGLE;
    int loc = OSKAR_CPU;

    int num_sources = oskar_sky_num_sources(sky);
    oskar_Mem *hor_x, *hor_y, *hor_z;
    hor_x = oskar_mem_create(type, loc, num_sources, &status);
    hor_y = oskar_mem_create(type, loc, num_sources, &status);
    hor_z = oskar_mem_create(type, loc, num_sources, &status);

    oskar_Mem *pp_lon, *pp_lat, *pp_rel_path;
    int num_stations = oskar_telescope_num_stations(tel);

    int num_pp = num_stations * num_sources;
    pp_lon = oskar_mem_create(type, loc, num_pp, &status);
    pp_lat = oskar_mem_create(type, loc, num_pp, &status);
    pp_rel_path = oskar_mem_create(type, loc, num_pp, &status);

    // Pierce points for one station (non-owned oskar_Mem pointers)
    oskar_Mem *pp_st_lon, *pp_st_lat, *pp_st_rel_path;
    pp_st_lon = oskar_mem_create_alias(0, 0, 0, &status);
    pp_st_lat = oskar_mem_create_alias(0, 0, 0, &status);
    pp_st_rel_path = oskar_mem_create_alias(0, 0, 0, &status);

    int num_times = settings.obs.num_time_steps;
    double obs_start_mjd_utc = settings.obs.start_mjd_utc;
    double dt_dump = settings.obs.dt_dump_days;

    // Binary file meta-data
    std::string label1 = "pp_lon";
    std::string label2 = "pp_lat";
    std::string label3 = "pp_path";
    std::string units  = "radians";
    std::string units2 = "";
    oskar_Mem *dims = oskar_mem_create(OSKAR_INT, loc, 2, &status);
    /* FIXME is this the correct dimension order ?
     * FIXME get the MATLAB reader to respect dimension ordering */
    oskar_mem_int(dims, &status)[0] = num_sources;
    oskar_mem_int(dims, &status)[1] = num_stations;

    const char* filename = settings.ionosphere.pierce_points.filename;
    oskar_Binary* h = oskar_binary_create(filename, 'w', &status);

    double screen_height_m = settings.ionosphere.TID->height_km * 1000.0;

//    printf("Number of times    = %i\n", num_times);
//    printf("Number of stations = %i\n", num_stations);

    void *x_, *y_, *z_;
    x_ = oskar_mem_void(oskar_telescope_station_true_x_offset_ecef_metres(tel));
    y_ = oskar_mem_void(oskar_telescope_station_true_y_offset_ecef_metres(tel));
    z_ = oskar_mem_void(oskar_telescope_station_true_z_offset_ecef_metres(tel));

    for (int t = 0; t < num_times; ++t)
    {
        double t_dump = obs_start_mjd_utc + t * dt_dump; // MJD UTC
        double gast = oskar_convert_mjd_to_gast_fast(t_dump + dt_dump / 2.0);

        for (int i = 0; i < num_stations; ++i)
        {
            const oskar_Station* station =
                    oskar_telescope_station_const(tel, i);
            double lon = oskar_station_lon_rad(station);
            double lat = oskar_station_lat_rad(station);
            double alt = oskar_station_alt_metres(station);
            double x_ecef, y_ecef, z_ecef, x_offset, y_offset, z_offset;

            if (type == OSKAR_DOUBLE)
            {
                x_offset = ((double*)x_)[i];
                y_offset = ((double*)y_)[i];
                z_offset = ((double*)z_)[i];
            }
            else
            {
                x_offset = (double)((float*)x_)[i];
                y_offset = (double)((float*)y_)[i];
                z_offset = (double)((float*)z_)[i];
            }

            oskar_convert_offset_ecef_to_ecef(1, &x_offset, &y_offset,
                    &z_offset, lon, lat, alt, &x_ecef, &y_ecef, &z_ecef);
            double last = gast + lon;

            if (type == OSKAR_DOUBLE)
            {
                oskar_convert_apparent_ra_dec_to_enu_directions_d(num_sources,
                        oskar_mem_double_const(oskar_sky_ra_rad_const(sky), &status),
                        oskar_mem_double_const(oskar_sky_dec_rad_const(sky), &status),
                        last, lat, oskar_mem_double(hor_x, &status),
                        oskar_mem_double(hor_y, &status),
                        oskar_mem_double(hor_z, &status));
            }
            else
            {
                oskar_convert_apparent_ra_dec_to_enu_directions_f(num_sources,
                        oskar_mem_float_const(oskar_sky_ra_rad_const(sky), &status),
                        oskar_mem_float_const(oskar_sky_dec_rad_const(sky), &status),
                        last, lat, oskar_mem_float(hor_x, &status),
                        oskar_mem_float(hor_y, &status),
                        oskar_mem_float(hor_z, &status));
            }

            int offset = i * num_sources;
            oskar_mem_set_alias(pp_st_lon, pp_lon, offset, num_sources,
                    &status);
            oskar_mem_set_alias(pp_st_lat, pp_lat, offset, num_sources,
                    &status);
            oskar_mem_set_alias(pp_st_rel_path, pp_rel_path, offset,
                    num_sources, &status);
            oskar_evaluate_pierce_points(pp_st_lon, pp_st_lat, pp_st_rel_path,
                    x_ecef, y_ecef, z_ecef, screen_height_m,
                    num_sources, hor_x, hor_y, hor_z, &status);
        } // Loop over stations.

        if (status != 0)
            continue;

        int index = t; // could be = (num_times * f) + t if we have frequency data
        int num_fields = 3;
        int num_field_tags = 4;
        double freq_hz = 0.0;
        int freq_idx = 0;

        // Write the header TAGS
        oskar_binary_write_int(h, GRP, TIME_IDX, index, t, &status);
        oskar_binary_write_double(h, GRP, FREQ_IDX, index, freq_idx, &status);
        oskar_binary_write_double(h, GRP, TIME_MJD_UTC, index, t_dump, &status);
        oskar_binary_write_double(h, GRP, FREQ_HZ, index, freq_hz, &status);
        oskar_binary_write_int(h, GRP, NUM_FIELDS, index, num_fields, &status);
        oskar_binary_write_int(h, GRP, NUM_FIELD_TAGS, index, num_field_tags,
                &status);

        // Write data TAGS (fields)
        int field, tagID;
        field = 0;
        tagID = HEADER_OFFSET + (num_field_tags * field);
        oskar_binary_write_mem(h, pp_lon, GRP, tagID + DATA,
                index, 0, &status);
        oskar_binary_write_mem(h, dims, GRP, tagID  + DIMS,
                index, 0, &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL,
                index, label1.size()+1, label1.c_str(), &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS,
                index, units.size()+1, units.c_str(), &status);
        field = 1;
        tagID = HEADER_OFFSET + (num_field_tags * field);
        oskar_binary_write_mem(h, pp_lat, GRP, tagID + DATA,
                index, 0, &status);
        oskar_binary_write_mem(h, dims, GRP, tagID  + DIMS,
                index, 0, &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL,
                index, label2.size()+1, label2.c_str(), &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS,
                index, units.size()+1, units.c_str(), &status);
        field = 2;
        tagID = HEADER_OFFSET + (num_field_tags * field);
        oskar_binary_write_mem(h, pp_rel_path, GRP, tagID + DATA,
                index, 0, &status);
        oskar_binary_write_mem(h, dims, GRP, tagID  + DIMS,
                index, 0, &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + LABEL,
                index, label3.size()+1, label3.c_str(), &status);
        oskar_binary_write(h, OSKAR_CHAR, GRP, tagID + UNITS,
                index, units2.size()+1, units2.c_str(), &status);
    } // Loop over times

    // Close the OSKAR binary file.
    oskar_binary_free(h);

    // clean up memory
    oskar_mem_free(hor_x, &status);
    oskar_mem_free(hor_y, &status);
    oskar_mem_free(hor_z, &status);
    oskar_mem_free(pp_lon, &status);
    oskar_mem_free(pp_lat, &status);
    oskar_mem_free(pp_rel_path, &status);
    oskar_mem_free(pp_st_lon, &status);
    oskar_mem_free(pp_st_lat, &status);
    oskar_mem_free(pp_st_rel_path, &status);
    oskar_mem_free(dims, &status);
    oskar_telescope_free(tel, &status);
    oskar_sky_free(sky, &status);

    // Check for errors.
    if (status)
        oskar_log_error(log, "Run failed: %s.", oskar_get_error_string(status));
    oskar_log_free(log);

    return status;
}
    void runTest(int prec1, int prec2, int loc1, int loc2, int matrix)
    {
        int status = 0, type;
        oskar_Mem *beam1, *beam2;
        oskar_Timer *timer1, *timer2;
        double time1, time2;

        // Create the timers.
        timer1 = oskar_timer_create(loc1 == OSKAR_GPU ?
                OSKAR_TIMER_CUDA : OSKAR_TIMER_NATIVE);
        timer2 = oskar_timer_create(loc2 == OSKAR_GPU ?
                OSKAR_TIMER_CUDA : OSKAR_TIMER_NATIVE);

        // Run first part.
        type = prec1 | OSKAR_COMPLEX;
        if (matrix) type |= OSKAR_MATRIX;
        beam1 = oskar_mem_create(type, loc1, num_sources, &status);
        oskar_mem_clear_contents(beam1, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        createTestData(prec1, loc1, matrix);
        oskar_timer_start(timer1);
        oskar_evaluate_cross_power(num_sources, num_stations,
                jones, 0, beam1, &status);
        time1 = oskar_timer_elapsed(timer1);
        destroyTestData();
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Run second part.
        type = prec2 | OSKAR_COMPLEX;
        if (matrix) type |= OSKAR_MATRIX;
        beam2 = oskar_mem_create(type, loc2, num_sources, &status);
        oskar_mem_clear_contents(beam2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        createTestData(prec2, loc2, matrix);
        oskar_timer_start(timer2);
        oskar_evaluate_cross_power(num_sources, num_stations,
                jones, 0, beam2, &status);
        time2 = oskar_timer_elapsed(timer2);
        destroyTestData();
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Destroy the timers.
        oskar_timer_free(timer1);
        oskar_timer_free(timer2);

        // Compare results.
        check_values(beam1, beam2);

        // Free memory.
        oskar_mem_free(beam1, &status);
        oskar_mem_free(beam2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Record properties for test.
        RecordProperty("JonesType", matrix ? "Matrix" : "Scalar");
        RecordProperty("Prec1", prec1 == OSKAR_SINGLE ? "Single" : "Double");
        RecordProperty("Loc1", loc1 == OSKAR_CPU ? "CPU" : "GPU");
        RecordProperty("Time1_ms", int(time1 * 1000));
        RecordProperty("Prec2", prec2 == OSKAR_SINGLE ? "Single" : "Double");
        RecordProperty("Loc2", loc2 == OSKAR_CPU ? "CPU" : "GPU");
        RecordProperty("Time2_ms", int(time2 * 1000));

#ifdef ALLOW_PRINTING
        // Print times.
        printf("  > %s.\n", matrix ? "Matrix" : "Scalar");
        printf("    %s precision %s: %.2f ms, %s precision %s: %.2f ms\n",
                prec1 == OSKAR_SINGLE ? "Single" : "Double",
                loc1 == OSKAR_CPU ? "CPU" : "GPU",
                time1 * 1000.0,
                prec2 == OSKAR_SINGLE ? "Single" : "Double",
                loc2 == OSKAR_CPU ? "CPU" : "GPU",
                time2 * 1000.0);
#endif
    }
Beispiel #23
0
int main(int argc, char** argv)
{
    oskar::OptionParser opt("oskar_correlator_benchmark", OSKAR_VERSION_STR);
    opt.add_flag("-nst", "Number of stations.", 1, "", true);
    opt.add_flag("-nsrc", "Number of sources.", 1, "", true);
    opt.add_flag("-sp", "Use single precision (default: double precision)");
    opt.add_flag("-s", "Use scalar Jones terms (default: matrix/polarised).");
    opt.add_flag("-g", "Run on the GPU");
    opt.add_flag("-c", "Run on the CPU");
    opt.add_flag("-e", "Use Gaussian sources (default: point sources).");
    opt.add_flag("-t", "Use analytical time averaging (default: no time "
            "averaging).");
    opt.add_flag("-r", "Dump raw iteration data to this file.", 1);
    opt.add_flag("-std", "Discard values greater than this number of standard "
            "deviations from the mean.", 1);
    opt.add_flag("-n", "Number of iterations", 1, "1", false);
    opt.add_flag("-v", "Display verbose output.", false);
    if (!opt.check_options(argc, argv))
        return EXIT_FAILURE;

    int num_stations, num_sources, niter;
    double max_std_dev = 0.0;
    opt.get("-nst")->getInt(num_stations);
    opt.get("-nsrc")->getInt(num_sources);
    int type = opt.is_set("-sp") ? OSKAR_SINGLE : OSKAR_DOUBLE;
    int jones_type = type | OSKAR_COMPLEX;
    if (!opt.is_set("-s"))
        jones_type |= OSKAR_MATRIX;
    opt.get("-n")->getInt(niter);
    int use_extended = opt.is_set("-e") ? OSKAR_TRUE : OSKAR_FALSE;
    int use_time_ave = opt.is_set("-t") ? OSKAR_TRUE : OSKAR_FALSE;
    std::string raw_file;
    if (opt.is_set("-r"))
        opt.get("-r")->getString(raw_file);
    if (opt.is_set("-std"))
        opt.get("-std")->getDouble(max_std_dev);

    int loc;
    if (opt.is_set("-g"))
        loc = OSKAR_GPU;
    if (opt.is_set("-c"))
        loc = OSKAR_CPU;
    if (!(opt.is_set("-c") ^ opt.is_set("-g")))
    {
        opt.error("Please select one of -g or -c");
        return EXIT_FAILURE;
    }

    if (opt.is_set("-v"))
    {
        printf("\n");
        printf("- Number of stations: %i\n", num_stations);
        printf("- Number of sources: %i\n", num_sources);
        printf("- Precision: %s\n", (type == OSKAR_SINGLE) ? "single" : "double");
        printf("- Jones type: %s\n", (opt.is_set("-s")) ? "scalar" : "matrix");
        printf("- Extended sources: %s\n", (use_extended) ? "true" : "false");
        printf("- Analytical time smearing: %s\n", (use_time_ave) ? "true" : "false");
        printf("- Number of iterations: %i\n", niter);
        if (max_std_dev > 0.0)
            printf("- Max standard deviations: %f\n", max_std_dev);
        if (!raw_file.empty())
            printf("- Writing iteration data to: %s\n", raw_file.c_str());
        printf("\n");
    }

    // Run benchmarks.
    double time_taken_sec = 0.0, average_time_sec = 0.0;
    std::vector<double> times;
    int status = benchmark(num_stations, num_sources, type, jones_type,
            loc, use_extended, use_time_ave, niter, times);

    // Compute total time taken.
    for (int i = 0; i < niter; ++i)
    {
        time_taken_sec += times[i];
    }

    // Dump raw data if requested.
    if (!raw_file.empty())
    {
        FILE* raw_stream = 0;
        raw_stream = fopen(raw_file.c_str(), "w");
        if (raw_stream)
        {
            for (int i = 0; i < niter; ++i)
            {
                fprintf(raw_stream, "%.6f\n", times[i]);
            }
            fclose(raw_stream);
        }
    }

    // Check for errors.
    if (status)
    {
        fprintf(stderr, "ERROR: correlate failed with code %i: %s\n", status,
                oskar_get_error_string(status));
        return EXIT_FAILURE;
    }

    // Compute average.
    if (max_std_dev > 0.0)
    {
        double std_dev_sec = 0.0, old_time_average_sec;

        // Compute standard deviation.
        old_time_average_sec = time_taken_sec / niter;
        for (int i = 0; i < niter; ++i)
        {
            std_dev_sec += pow(times[i] - old_time_average_sec, 2.0);
        }
        std_dev_sec /= niter;
        std_dev_sec = sqrt(std_dev_sec);

        // Compute new mean.
        average_time_sec = 0.0;
        int counter = 0;
        for (int i = 0; i < niter; ++i)
        {
            if (fabs(times[i] - old_time_average_sec) <
                    max_std_dev * std_dev_sec)
            {
                average_time_sec += times[i];
                counter++;
            }
        }
        if (counter)
            average_time_sec /= counter;
    }
    else
    {
        average_time_sec = time_taken_sec / niter;
    }

    // Print average.
    if (opt.is_set("-v"))
    {
        printf("==> Total time taken: %f seconds.\n", time_taken_sec);
        printf("==> Time taken per iteration: %f seconds.\n", average_time_sec);
        printf("==> Iteration values:\n");
        for (int i = 0; i < niter; ++i)
        {
            printf("%.6f\n", times[i]);
        }
        printf("\n");
    }
    else
    {
        printf("%f\n", average_time_sec);
    }

    return EXIT_SUCCESS;
}
Beispiel #24
0
    void runTest(int prec1, int prec2, int loc1, int loc2, int matrix,
            int extended, double time_average)
    {
        int num_baselines, status = 0, type;
        oskar_Mem *vis1, *vis2;
        oskar_Timer *timer1, *timer2;
        double time1, time2, frequency = 100e6;

        // Create the timers.
        timer1 = oskar_timer_create(loc1 == OSKAR_GPU ?
                OSKAR_TIMER_CUDA : OSKAR_TIMER_NATIVE);
        timer2 = oskar_timer_create(loc2 == OSKAR_GPU ?
                OSKAR_TIMER_CUDA : OSKAR_TIMER_NATIVE);

        // Run first part.
        createTestData(prec1, loc1, matrix);
        num_baselines = oskar_telescope_num_baselines(tel);
        type = prec1 | OSKAR_COMPLEX;
        if (matrix) type |= OSKAR_MATRIX;
        vis1 = oskar_mem_create(type, loc1, num_baselines, &status);
        oskar_mem_clear_contents(vis1, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_sky_set_use_extended(sky, extended);
        oskar_telescope_set_channel_bandwidth(tel, bandwidth);
        oskar_telescope_set_time_average(tel, time_average);
        oskar_timer_start(timer1);
        oskar_cross_correlate(vis1, oskar_sky_num_sources(sky), jones, sky,
                tel, u_, v_, w_, 1.0, frequency, &status);
        time1 = oskar_timer_elapsed(timer1);
        destroyTestData();
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Run second part.
        createTestData(prec2, loc2, matrix);
        num_baselines = oskar_telescope_num_baselines(tel);
        type = prec2 | OSKAR_COMPLEX;
        if (matrix) type |= OSKAR_MATRIX;
        vis2 = oskar_mem_create(type, loc2, num_baselines, &status);
        oskar_mem_clear_contents(vis2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);
        oskar_sky_set_use_extended(sky, extended);
        oskar_telescope_set_channel_bandwidth(tel, bandwidth);
        oskar_telescope_set_time_average(tel, time_average);
        oskar_timer_start(timer2);
        oskar_cross_correlate(vis2, oskar_sky_num_sources(sky), jones, sky,
                tel, u_, v_, w_, 1.0, frequency, &status);
        time2 = oskar_timer_elapsed(timer2);
        destroyTestData();
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Destroy the timers.
        oskar_timer_free(timer1);
        oskar_timer_free(timer2);

        // Compare results.
        check_values(vis1, vis2);

        // Free memory.
        oskar_mem_free(vis1, &status);
        oskar_mem_free(vis2, &status);
        ASSERT_EQ(0, status) << oskar_get_error_string(status);

        // Record properties for test.
        RecordProperty("SourceType", extended ? "Gaussian" : "Point");
        RecordProperty("JonesType", matrix ? "Matrix" : "Scalar");
        RecordProperty("TimeSmearing", time_average == 0.0 ? "off" : "on");
        RecordProperty("Prec1", prec1 == OSKAR_SINGLE ? "Single" : "Double");
        RecordProperty("Loc1", loc1 == OSKAR_CPU ? "CPU" : "GPU");
        RecordProperty("Time1_ms", int(time1 * 1000));
        RecordProperty("Prec2", prec2 == OSKAR_SINGLE ? "Single" : "Double");
        RecordProperty("Loc2", loc2 == OSKAR_CPU ? "CPU" : "GPU");
        RecordProperty("Time2_ms", int(time2 * 1000));

#ifdef ALLOW_PRINTING
        // Print times.
        printf("  > %s. %s sources. Time smearing %s.\n",
                matrix ? "Matrix" : "Scalar",
                extended ? "Gaussian" : "Point",
                time_average == 0.0 ? "off" : "on");
        printf("    %s precision %s: %.2f ms, %s precision %s: %.2f ms\n",
                prec1 == OSKAR_SINGLE ? "Single" : "Double",
                loc1 == OSKAR_CPU ? "CPU" : "GPU",
                time1 * 1000.0,
                prec2 == OSKAR_SINGLE ? "Single" : "Double",
                loc2 == OSKAR_CPU ? "CPU" : "GPU",
                time2 * 1000.0);
#endif
    }
Beispiel #25
0
TEST(fit_ellipse, test1)
{
    int num_points = 7, status = 0;
    double maj_d = 0.0, min_d = 0.0, pa_d = 0.0;
    float maj_f = 0.0, min_f = 0.0, pa_f = 0.0;

    // Test double precision.
    {
        std::vector<double> x(num_points), y(num_points);
        std::vector<double> work1(5 * num_points), work2(5 * num_points);
        x[0] = -0.1686;
        x[1] = -0.0921;
        x[2] =  0.0765;
        x[3] =  0.1686;
        x[4] =  0.0921;
        x[5] = -0.0765;
        x[6] = -0.1686;

        y[0] =  0.7282;
        y[1] =  0.6994;
        y[2] =  0.6675;
        y[3] =  0.6643;
        y[4] =  0.7088;
        y[5] =  0.7407;
        y[6] =  0.7282;

        oskar_fit_ellipse_d(&maj_d, &min_d, &pa_d, num_points, &x[0], &y[0],
                &work1[0], &work2[0], &status);
        EXPECT_EQ(0, status) << oskar_get_error_string(status);
    }

    // Test single precision.
    {
        std::vector<float> x(num_points), y(num_points);
        std::vector<float> work1(5 * num_points), work2(5 * num_points);
        x[0] = -0.1686;
        x[1] = -0.0921;
        x[2] =  0.0765;
        x[3] =  0.1686;
        x[4] =  0.0921;
        x[5] = -0.0765;
        x[6] = -0.1686;

        y[0] =  0.7282;
        y[1] =  0.6994;
        y[2] =  0.6675;
        y[3] =  0.6643;
        y[4] =  0.7088;
        y[5] =  0.7407;
        y[6] =  0.7282;

        oskar_fit_ellipse_f(&maj_f, &min_f, &pa_f, num_points, &x[0], &y[0],
                &work1[0], &work2[0], &status);
        EXPECT_EQ(0, status) << oskar_get_error_string(status);
    }

    // Compare results.
    EXPECT_NEAR(maj_d, 0.3608619735, 1e-9);
    EXPECT_NEAR(min_d, 0.0494223702, 1e-9);
    EXPECT_NEAR(pa_d, -1.3865537748, 1e-9);
    EXPECT_NEAR(maj_d, maj_f, 1e-5);
    EXPECT_NEAR(min_d, min_f, 1e-5);
    EXPECT_NEAR(pa_d, pa_f, 1e-5);
}
Beispiel #26
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;
}