Skip to content

Commit

Permalink
eckit::geometry ORCA
Browse files Browse the repository at this point in the history
  • Loading branch information
pmaciel committed Aug 23, 2023
1 parent 12ba578 commit 0663703
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 17 deletions.
160 changes: 153 additions & 7 deletions src/eckit/geometry/grid/ORCA.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,21 @@

#include "eckit/geometry/grid/ORCA.h"

#include "eckit/codec/codec.h"
#include "eckit/exception/Exceptions.h"
#include "eckit/filesystem/PathName.h"
#include "eckit/filesystem/URI.h"
#include "eckit/geometry/LibEcKitGeometry.h"
#include "eckit/geometry/area/BoundingBox.h"
#include "eckit/io/Length.h"
#include "eckit/log/Bytes.h"
#include "eckit/log/Timer.h"
#include "eckit/utils/ByteSwap.h"
#include "eckit/utils/MD5.h"

#ifdef eckit_HAVE_CURL
#include "eckit/io/URLHandle.h"
#endif


namespace eckit::geometry::grid {
Expand All @@ -32,9 +45,13 @@ ORCA::Arrangement arrangement_from_string(const std::string& str) {
}


size_t dimension(const std::vector<size_t>& dim, size_t index) {
ASSERT(dim.size() == 2 && index < 2);
return dim[index];
std::string arrangement_to_string(ORCA::Arrangement a) {
return a == ORCA::Arrangement::F ? "F"
: a == ORCA::Arrangement::T ? "T"
: a == ORCA::Arrangement::U ? "U"
: a == ORCA::Arrangement::V ? "V"
: a == ORCA::Arrangement::W ? "W"
: throw AssertionFailed("ORCA::Arrangement", Here());
}


Expand Down Expand Up @@ -90,19 +107,148 @@ Point ORCA::Iterator::operator*() const {

ORCA::ORCA(const Configuration& config) :
Grid(config),
ni_(dimension(config.getUnsignedVector("dimensions"), 0)),
nj_(dimension(config.getUnsignedVector("dimensions"), 1)),
name_(config.getString("orca_name")),
uid_(config.getString("orca_uid")),
arrangement_(arrangement_from_string(config.getString("orca_arrangement"))) {
ASSERT(0 < ni_);
ASSERT(0 < nj_);


// TODO
ASSERT(0 < dimensions_[0]);
ASSERT(0 < dimensions_[1]);

ASSERT(halo_[0] >= 0);
ASSERT(halo_[1] >= 0);
ASSERT(halo_[2] >= 0);
ASSERT(halo_[3] >= 0);

ASSERT(pivot_[0] >= 0);
ASSERT(pivot_[1] >= 0);

size_t size = dimensions_[0] * dimensions_[1];
ASSERT(0 < size);
ASSERT(longitudes_.size() == size);
ASSERT(latitudes_.size() == size);
ASSERT(flags_.size() == size);


auto url = config.getString("url_prefix", "") + config.getString("url");
Log::info() << "url: '" << url << "'" << std::endl;
}


ORCA::ORCA(const URI& uri) :
Grid(area::BoundingBox::make_global_prime()) {
if (uri.scheme().find("http") == 0) {
PathName path = "..."; // from url

if (!path.exists() && LibEcKitGeometry::caching()) {
Timer timer;


Log::debug() << "Downloading " << uri << " to " << path << std::endl;

path.dirName().mkdir();

PathName tmp = path + ".download";
Length length = 0;

#if eckit_HAVE_CURL
try {
length = URLHandle(uri.asRawString()).saveInto(tmp);
}
catch (...) {
length = 0;
}
#endif

if (length <= 0) {
if (tmp.exists()) {
tmp.unlink(true);
}

throw UserError("Could not download file from url " + uri.asRawString());
}

if (!path.exists()) {
throw UserError("Could not locate orca grid data file " + path);
}

PathName::rename(tmp, path);

Log::info() << "Download of " << Bytes(length) << " took " << timer.elapsed() << " s." << std::endl;
}
else {
throw UserError("Could not locate orca grid data file " + path);
}
}
else {
if (!uri.path().exists()) {
throw UserError("Could not locate orca grid data file " + uri.asRawString());
}
}
}


void ORCA::read(const PathName& p) {
codec::RecordReader reader(p);

int version = -1;
reader.read("version", version).wait();

if (version == 0) {
reader.read("dimensions", dimensions_);
reader.read("pivot", pivot_);
reader.read("halo", halo_);
reader.read("longitude", longitudes_);
reader.read("latitude", latitudes_);
reader.read("flags", flags_);
reader.wait();
}
else {
ASSERT_MSG(false, "Unsupported version ");
}
}


size_t ORCA::write(const PathName& p, const std::string& compression) {
codec::RecordWriter record;

record.compression(compression);
record.set("version", 0);
record.set("dimensions", dimensions_);
record.set("halo", halo_);
record.set("pivot", pivot_);
record.set("longitude", codec::ArrayReference(longitudes_.data(), dimensions_));
record.set("latitude", codec::ArrayReference(latitudes_.data(), dimensions_));
record.set("flags", codec::ArrayReference(flags_.data(), dimensions_));

return record.write(p);
}


std::string ORCA::uid(const Configuration& config) const {
MD5 hash;
hash.add(arrangement_to_string(arrangement_));

auto sized = static_cast<long>(longitudes_.size() * sizeof(double));

if constexpr (eckit_LITTLE_ENDIAN) {
hash.add(latitudes_.data(), sized);
hash.add(longitudes_.data(), sized);
}
else {
auto lonsw = longitudes_;
auto latsw = latitudes_;
eckit::byteswap(latsw.data(), latsw.size());
eckit::byteswap(lonsw.data(), lonsw.size());
hash.add(latsw.data(), sized);
hash.add(lonsw.data(), sized);
}

return hash.digest();
}


Configuration* ORCA::config(const std::string& name) {
return GridConfigurationUID::instance().get(name).config();
}
Expand Down
37 changes: 27 additions & 10 deletions src/eckit/geometry/grid/ORCA.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@

#pragma once

#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>

#include "eckit/geometry/Grid.h"


namespace eckit {
class PathName;
class URI;
} // namespace eckit


namespace eckit::geometry::grid {


Expand Down Expand Up @@ -60,6 +70,7 @@ class ORCA final : public Grid {
// -- Constructors

explicit ORCA(const Configuration&);
explicit ORCA(const URI&);

// -- Destructor
// None
Expand All @@ -71,7 +82,11 @@ class ORCA final : public Grid {
// None

// -- Methods
// None

void read(const PathName&);
size_t write(const PathName&, const std::string& compression = "none");

std::string uid(const Configuration& config) const;

// -- Overridden methods
// None
Expand All @@ -86,19 +101,22 @@ class ORCA final : public Grid {
private:
// -- Members

const size_t ni_;
const size_t nj_;
const std::string name_;
const std::string uid_;
const Arrangement arrangement_;
std::string name_;
std::string uid_;
Arrangement arrangement_;

std::vector<double> longitudes_;
std::vector<double> latitudes_;

std::array<std::int32_t, 2> dimensions_{-1, -1};
std::array<std::int32_t, 4> halo_{-1, -1, -1, -1};
std::array<double, 2> pivot_{-1, -1};
std::vector<std::byte> flags_;

// -- Methods

size_t ni() const { return ni_; }
size_t nj() const { return nj_; }
size_t ni() const { return static_cast<size_t>(dimensions_[0]); }
size_t nj() const { return static_cast<size_t>(dimensions_[1]); }

std::vector<double> longitudes(size_t ring) const;

Expand Down Expand Up @@ -126,8 +144,7 @@ class ORCA final : public Grid {
// None

// -- Friends

friend class RingIterator;
// None
};


Expand Down

0 comments on commit 0663703

Please sign in to comment.