Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/eckit geo #275

Merged
merged 5 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ ecbuild_add_option( FEATURE GEOGRAPHY
DESCRIPTION "Support for Geoiterator and nearest neighbour"
DEFAULT ON )

ecbuild_add_option( FEATURE ECKIT_GEO
DESCRIPTION "Support for Geoiterator and nearest neighbour (additional backend)"
CONDITION ENABLE_GEOGRAPHY
DEFAULT OFF )

if( eccodes_HAVE_ECKIT_GEO AND NOT TARGET eckit_geo )
ecbuild_find_package(NAME eckit VERSION 1.27 REQUIRED)
if( NOT TARGET eckit_geo )
ecbuild_critical("eckit has not been built with ECKIT_GEO enabled")
endif()
endif()

ecbuild_add_option( FEATURE JPG
DESCRIPTION "Support for JPG decoding/encoding"
DEFAULT ON )
Expand Down Expand Up @@ -485,7 +497,7 @@ ecbuild_pkgconfig(
IGNORE_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} ${NETCDF_INCLUDE_DIRS}
VARIABLES HAVE_MEMFS HAVE_GEOGRAPHY HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG
HAVE_ECCODES_THREADS HAVE_ECCODES_OMP_THREADS
HAVE_NETCDF HAVE_FORTRAN HAVE_PNG HAVE_AEC
HAVE_NETCDF HAVE_FORTRAN HAVE_PNG HAVE_AEC HAVE_ECKIT_GEO
)
if( HAVE_FORTRAN )
ecbuild_pkgconfig(
Expand All @@ -497,7 +509,7 @@ if( HAVE_FORTRAN )
${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS} ${NETCDF_INCLUDE_DIRS}
VARIABLES HAVE_MEMFS HAVE_GEOGRAPHY HAVE_JPEG HAVE_LIBJASPER HAVE_LIBOPENJPEG
HAVE_ECCODES_THREADS HAVE_ECCODES_OMP_THREADS
HAVE_NETCDF HAVE_PNG HAVE_AEC
HAVE_NETCDF HAVE_PNG HAVE_AEC HAVE_ECKIT_GEO
)
endif()

Expand Down
1 change: 1 addition & 0 deletions eccodes_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
#cmakedefine HAVE_NETCDF

#cmakedefine HAVE_GEOGRAPHY
#cmakedefine HAVE_ECKIT_GEO
#cmakedefine HAVE_MEMFS
#cmakedefine HAVE_FORTRAN

Expand Down
9 changes: 9 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,15 @@ if( HAVE_MEMFS )
list(APPEND ECCODES_EXTRA_LIBRARIES eccodes_memfs)
endif()

if( eccodes_HAVE_GEOGRAPHY AND eccodes_HAVE_ECKIT_GEO )
list( APPEND eccodes_src_files
eccodes/geo/GeoIterator.cc
eccodes/geo/GeoIterator.h
eccodes/geo/GribSpec.cc
eccodes/geo/GribSpec.h )
list( APPEND ECCODES_EXTRA_LIBRARIES eckit_geo )
endif()

ecbuild_add_library( TARGET eccodes
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/grib_api_version.cc
# griby.cc gribl.cc
Expand Down
104 changes: 104 additions & 0 deletions src/eccodes/geo/GeoIterator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* (C) Copyright 2024- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
*
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
*/


#include "eccodes/geo/GeoIterator.h"

#include "eckit/exception/Exceptions.h"

#include "eccodes/geo/GribSpec.h"


namespace eccodes::geo
{


GeoIterator::GeoIterator(grib_handle* h, unsigned long flags) :
spec_(new GribSpec(h)), grid_(eckit::geo::GridFactory::build(*spec_)), iter_(grid_->cbegin().release()), end_(grid_->cend().release())
{
h_ = h;
class_name_ = "geo_iterator";
flags_ = flags;
Assert(h_ != nullptr);

CODES_CHECK(codes_get_size(h_, "values", &nv_), "");
Assert(nv_ > 0);

data_ = (flags_ & GRIB_GEOITERATOR_NO_VALUES) ? nullptr : static_cast<double*>(grib_context_malloc(h_->context, nv_ * sizeof(double)));
Assert(data_ != nullptr);

auto size = nv_;
CODES_CHECK(codes_get_double_array(h_, "values", data_, &size), "");
Assert(nv_ == size);
}


int GeoIterator::init(grib_handle*, grib_arguments*)
{
NOTIMP;
}


int GeoIterator::next(double* lat, double* lon, double* val) const
{
if (iter_ == end_) {
return 0; // (false)
}

const auto p = *iter_;
const auto& q = std::get<eckit::geo::PointLonLat>(p);

*lat = q.lat;
*lon = q.lon;
if (val != nullptr && data_ != nullptr) {
*val = data_[iter_->index()];
}

++iter_;
return 1; // (true)
}


int GeoIterator::previous(double*, double*, double*) const
{
return GRIB_NOT_IMPLEMENTED;
}


int GeoIterator::reset()
{
iter_.reset(grid_->cbegin().release());
return GRIB_SUCCESS;
}


int GeoIterator::destroy()
{
if (data_ != nullptr) {
grib_context_free(h_->context, data_);
}
return Iterator::destroy();
}


bool GeoIterator::has_next() const
{
return iter_ != end_;
}


geo_iterator::Iterator*
GeoIterator::create() const
{
return new GeoIterator{ h_, flags_ };
}


} // namespace eccodes::geo
51 changes: 51 additions & 0 deletions src/eccodes/geo/GeoIterator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* (C) Copyright 2024- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
*
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
*/


#pragma once

#include <memory>

#include "eckit/geo/Grid.h"

// eccodes macros conflict with eckit
#ifdef Assert
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a problem. It will be difficult to remove the usage of the eckit ASSERT macro from not only eckit, atlas and mir, but also metkit, pgen, mars-client, mars-client-c++ (and very likely metview Regrid). Internally, it calls global namespace "Assert" which clashes with the same symbol in eccodes.

In my opinion, libraries such as eckit should NOT export any macros, but this one does. And so does eccodes, and so there is a conflict. I believe the changin of this function in "the right way" is a very large refactoring which should be out of scope of this one.

#undef Assert
#endif

#include "geo_iterator/grib_iterator.h"


namespace eccodes::geo
{


class GeoIterator : public geo_iterator::Iterator
{
public:
explicit GeoIterator(grib_handle*, unsigned long flags);

private:
std::unique_ptr<const eckit::geo::Spec> spec_;
std::unique_ptr<const eckit::geo::Grid> grid_;
mutable eckit::geo::Grid::Iterator iter_;
eckit::geo::Grid::Iterator end_;

int init(grib_handle*, grib_arguments*) override;
int next(double* lat, double* lon, double* val) const override;
int previous(double* lat, double* lon, double* val) const override;
int reset() override;
int destroy() override;
bool has_next() const override;
geo_iterator::Iterator* create() const override;
};


} // namespace eccodes::geo
Loading
Loading