9 #include <unordered_set> 
   11 #include <boost/make_unique.hpp> 
   13 #include "atlas/mesh.h" 
   14 #include "atlas/meshgenerator.h" 
   15 #include "atlas/util/PolygonLocator.h" 
   16 #include "atlas/util/PolygonXY.h" 
   18 #include "eckit/mpi/Comm.h" 
   19 #include "ioda/distribution/AtlasDistribution.h" 
   20 #include "ioda/distribution/DistributionFactory.h" 
   21 #include "oops/util/Logger.h" 
   43   void assignRecord(std::size_t recNum, 
const eckit::geometry::Point2 & point);
 
   49   bool isInMyDomain(
const eckit::geometry::Point2 & point) 
const;
 
   53   std::unique_ptr<atlas::util::PolygonLocator> 
locator_;
 
   61   eckit::LocalConfiguration gridConfig(config, 
"grid");
 
   62   atlas::util::Config atlasConfig(gridConfig);
 
   64   atlas::Grid grid(atlasConfig);
 
   66   atlasConfig.set(
"type", grid.meshgenerator().getString(
"type"));
 
   67   atlas::MeshGenerator generator(atlasConfig);
 
   69   mesh_ = generator.generate(grid);
 
   70   if (
mesh_->nb_partitions() != atlas::mpi::comm().size()) {
 
   71     std::stringstream msg;
 
   72     msg << 
"The number of mesh partitions, " << 
mesh_->nb_partitions()
 
   73         << 
", is different from the number of MPI processes, " << atlas::mpi::comm().size();
 
   74     throw eckit::Exception(msg.str(), Here());
 
   77   locator_ = boost::make_unique<atlas::util::PolygonLocator>(
 
   78         atlas::util::ListPolygonXY(
mesh_.polygons()), 
mesh_.projection());
 
   82                                                      const eckit::geometry::Point2 & point) {
 
   83   if (recNum == nextRecordToAssign_) {
 
   84     const bool myRecord = isInMyDomain(point);
 
   85     oops::Log::debug() << 
"RecordAssigner::assignRecord(): is " << recNum << 
" my record? " 
   86                        << myRecord << std::endl;
 
   88       myRecords_.insert(recNum);
 
   89     ++nextRecordToAssign_;
 
   92     ASSERT(recNum < nextRecordToAssign_);
 
   97   return myRecords_.find(recNum) != myRecords_.end();
 
  101   const atlas::idx_t partition = (*locator_)(point);
 
  102   oops::Log::debug() << 
"RecordAssigner::isInMyDomain(): Polygon locator says " 
  103                      << point << 
" is in domain " << partition << std::endl;
 
  104   return partition == atlas::mpi::comm().rank();
 
  112                                    const eckit::Configuration & config)
 
  116   oops::Log::trace() << 
"AtlasDistribution constructed" << std::endl;
 
  120   oops::Log::trace() << 
"AtlasDistribution destructed" << std::endl;
 
  124                                     const std::size_t locNum,
 
  125                                     const eckit::geometry::Point2 & point) {
 
Assigns records to MPI ranks for the AtlasDistribution.
 
void assignRecord(std::size_t recNum, const eckit::geometry::Point2 &point)
 
std::size_t nextRecordToAssign_
 
std::unordered_set< std::size_t > myRecords_
 
bool isInMyDomain(const eckit::geometry::Point2 &point) const
 
std::unique_ptr< atlas::util::PolygonLocator > locator_
 
RecordAssigner(const eckit::Configuration &config)
 
bool isMyRecord(std::size_t recNum) const
Returns true if record recNum has been assigned to the calling process, false otherwise.
 
AtlasDistribution(const eckit::mpi::Comm &comm, const eckit::Configuration &config)
 
bool isMyRecord(std::size_t recNum) const override
Returns true if record RecNum has been assigned to the calling PE during a previous call to assignRec...
 
std::string name() const override
 
void assignRecord(const std::size_t recNum, const std::size_t locNum, const eckit::geometry::Point2 &point) override
If the record RecNum has not yet been assigned to a PE, assigns it to the appropriate PE.
 
std::unique_ptr< RecordAssigner > recordAssigner_
 
~AtlasDistribution() override
 
A class able to instantiate objects of type T, which should be a subclass of Distribution.
 
Implements some methods of Distribution in a manner suitable for distributions storing each observati...
 
void assignRecord(const std::size_t RecNum, const std::size_t LocNum, const eckit::geometry::Point2 &point) override
If the record RecNum has not yet been assigned to a PE, assigns it to the appropriate PE.
 
static DistributionMaker< AtlasDistribution > maker(DIST_NAME)