atlas
Structured.h
1 /*
2  * (C) Copyright 2013 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation
8  * nor does it submit to any jurisdiction.
9  */
10 
11 #pragma once
12 
13 #include <array>
14 #include <memory>
15 
16 #include "atlas/grid/Spacing.h"
17 #include "atlas/grid/detail/grid/Grid.h"
18 #include "atlas/grid/detail/spacing/LinearSpacing.h"
19 #include "atlas/library/config.h"
20 #include "atlas/runtime/Exception.h"
21 #include "atlas/util/Object.h"
22 #include "atlas/util/ObjectHandle.h"
23 #include "atlas/util/Point.h"
24 
25 namespace atlas {
26 namespace grid {
27 namespace detail {
28 namespace grid {
29 
39 class Structured : public Grid {
40 private:
41  struct ComputePointXY {
42  ComputePointXY( const Structured& grid ) : grid_( grid ), ny_( grid_.ny() ) {}
43  void operator()( idx_t i, idx_t j, PointXY& point ) {
44  if ( j < ny_ ) { // likely
45  grid_.xy( i, j, point.data() );
46  }
47  }
48  const Structured& grid_;
49  idx_t ny_;
50  };
51  struct ComputePointLonLat {
52  ComputePointLonLat( const Structured& grid ) : grid_( grid ), ny_( grid_.ny() ) {}
53  void operator()( idx_t i, idx_t j, PointLonLat& point ) {
54  if ( j < ny_ ) { // likely
55  grid_.lonlat( i, j, point.data() );
56  }
57  }
58  const Structured& grid_;
59  idx_t ny_;
60  };
61 
62  template <typename Base, typename ComputePoint>
63  class StructuredIterator : public Base {
64  public:
65  StructuredIterator( const Structured& grid, bool begin = true ) :
66  grid_( grid ), ny_( grid_.ny() ), i_( 0 ), j_( begin ? 0 : grid_.ny() ), compute_point{grid_} {
67  if ( j_ != ny_ && grid_.size() ) {
68  compute_point( i_, j_, point_ );
69  }
70  }
71  virtual bool next( typename Base::value_type& point ) {
72  if ( j_ < ny_ && i_ < grid_.nx( j_ ) ) {
73  compute_point( i_++, j_, point );
74 
75  if ( i_ == grid_.nx( j_ ) ) {
76  j_++;
77  i_ = 0;
78  }
79  return true;
80  }
81  return false;
82  }
83 
84  virtual const typename Base::reference operator*() const { return point_; }
85 
86  virtual const Base& operator++() {
87  ++i_;
88  if ( i_ == grid_.nx( j_ ) ) {
89  ++j_;
90  i_ = 0;
91  }
92  compute_point( i_, j_, point_ );
93  return *this;
94  }
95 
96  virtual const Base& operator+=( typename Base::difference_type distance ) {
97  idx_t d = distance;
98  while ( j_ != ny_ && d >= ( grid_.nx( j_ ) - i_ ) ) {
99  d -= ( grid_.nx( j_ ) - i_ );
100  ++j_;
101  i_ = 0;
102  }
103  i_ += d;
104  compute_point( i_, j_, point_ );
105  return *this;
106  }
107 
108  virtual typename Base::difference_type distance( const Base& other ) const {
109  const auto& _other = static_cast<const StructuredIterator&>( other );
110  typename Base::difference_type d = 0;
111  idx_t j = j_;
112  idx_t i = i_;
113  while ( j < _other.j_ ) {
114  d += grid_.nx( j ) - i;
115  ++j;
116  i = 0;
117  }
118  d += _other.i_;
119  return d;
120  }
121 
122  virtual bool operator==( const Base& other ) const {
123  return j_ == static_cast<const StructuredIterator&>( other ).j_ &&
124  i_ == static_cast<const StructuredIterator&>( other ).i_;
125  }
126 
127  virtual bool operator!=( const Base& other ) const {
128  return i_ != static_cast<const StructuredIterator&>( other ).i_ ||
129  j_ != static_cast<const StructuredIterator&>( other ).j_;
130  }
131 
132  virtual std::unique_ptr<Base> clone() const {
133  auto result = new StructuredIterator( grid_, false );
134  result->i_ = i_;
135  result->j_ = j_;
136  result->point_ = point_;
137  return std::unique_ptr<Base>( result );
138  }
139 
140  public:
141  const Structured& grid_;
142  idx_t ny_;
143  idx_t i_;
144  idx_t j_;
145  typename Base::value_type point_;
146  ComputePoint compute_point;
147  };
148 
149 public:
150  using IteratorXY = StructuredIterator<Grid::IteratorXY, ComputePointXY>;
151  using IteratorLonLat = StructuredIterator<Grid::IteratorLonLat, ComputePointLonLat>;
152 
153 public:
154  class XSpace {
155  class Implementation : public util::Object {
156  public:
157  // Constructor NVector can be either std::vector<int> or std::vector<long>
158  template <typename NVector>
159  Implementation( const std::array<double, 2>& interval, const NVector& N, bool endpoint = true );
160 
161  Implementation( const std::array<double, 2>& interval, std::initializer_list<int>&& N,
162  bool endpoint = true );
163 
164  Implementation( const Spacing&, idx_t ny = 1 );
165 
166  Implementation( const std::vector<Spacing>& );
167 
168  Implementation( const Config& );
169 
170  Implementation( const std::vector<Config>& );
171 
172  Implementation( const std::vector<spacing::LinearSpacing::Params>& );
173 
174  idx_t ny() const { return ny_; }
175 
176  // Minimum number of points across parallels (constant y)
177  idx_t nxmin() const { return nxmin_; }
178 
179  // Maximum number of points across parallels (constant y)
180  idx_t nxmax() const { return nxmax_; }
181 
183  const std::vector<idx_t>& nx() const { return nx_; }
184 
186  const std::vector<double>& xmin() const { return xmin_; }
187 
189  const std::vector<double>& xmax() const { return xmax_; }
190 
192  const std::vector<double>& dx() const { return dx_; }
193 
195  double min() const { return min_; }
196 
198  double max() const { return max_; }
199 
200  Spec spec() const;
201 
202  std::string type() const;
203 
204  private:
205  void reserve( idx_t ny );
206 
207  private:
208  idx_t ny_;
209  idx_t nxmin_;
210  idx_t nxmax_;
211  std::vector<idx_t> nx_;
212  std::vector<double> xmin_;
213  std::vector<double> xmax_;
214  std::vector<double> dx_;
215  double min_;
216  double max_;
217  };
218 
219  public:
220  XSpace();
221 
222  XSpace( const XSpace& );
223 
224  XSpace( const Spacing&, idx_t ny = 1 );
225 
226  XSpace( const std::vector<Spacing>& );
227 
228  XSpace( const std::vector<spacing::LinearSpacing::Params>& );
229 
230  // Constructor NVector can be either std::vector<int> or std::vector<long> or initializer list
231  template <typename NVector>
232  XSpace( const std::array<double, 2>& interval, const NVector& N, bool endpoint = true );
233 
234  XSpace( const std::array<double, 2>& interval, std::initializer_list<int>&& N, bool endpoint = true );
235 
236  XSpace( const Config& );
237 
238  XSpace( const std::vector<Config>& );
239 
240  idx_t ny() const { return impl_->ny(); }
241 
242  // Minimum number of points across parallels (constant y)
243  idx_t nxmin() const { return impl_->nxmin(); }
244 
245  // Maximum number of points across parallels (constant y)
246  idx_t nxmax() const { return impl_->nxmax(); }
247 
249  const std::vector<idx_t>& nx() const { return impl_->nx(); }
250 
252  const std::vector<double>& xmin() const { return impl_->xmin(); }
253 
255  const std::vector<double>& xmax() const { return impl_->xmax(); }
256 
258  const std::vector<double>& dx() const { return impl_->dx(); }
259 
261  double min() const { return impl_->min(); }
262 
264  double max() const { return impl_->max(); }
265 
266  Spec spec() const;
267 
268  std::string type() const { return impl_->type(); }
269 
270  private:
272  };
273 
274  using YSpace = Spacing;
275 
276 public:
277  static std::string static_type();
278 
279 public:
280  Structured( const std::string&, XSpace, YSpace, Projection, Domain );
282  Structured( const Structured&, Domain );
283 
284  virtual ~Structured() override;
285 
286  virtual idx_t size() const override { return npts_; }
287 
288  virtual Spec spec() const override;
289 
295  virtual std::string name() const override;
296 
297  virtual std::string type() const override;
298 
299  inline idx_t ny() const { return static_cast<idx_t>( y_.size() ); }
300 
301  inline idx_t nx( idx_t j ) const { return static_cast<idx_t>( nx_[j] ); }
302 
303  inline idx_t nxmax() const { return nxmax_; }
304 
305  inline idx_t nxmin() const { return nxmin_; }
306 
307  inline const std::vector<idx_t>& nx() const { return nx_; }
308 
309  inline const std::vector<double>& y() const { return y_; }
310 
311  inline double dx( idx_t j ) const { return dx_[j]; }
312 
313  inline double xmin( idx_t j ) const { return xmin_[j]; }
314 
315  inline double x( idx_t i, idx_t j ) const { return xmin_[j] + static_cast<double>( i ) * dx_[j]; }
316 
317  inline double y( idx_t j ) const { return y_[j]; }
318 
319  inline void xy( idx_t i, idx_t j, double crd[] ) const {
320  crd[0] = x( i, j );
321  crd[1] = y( j );
322  }
323 
324  PointXY xy( idx_t i, idx_t j ) const { return PointXY( x( i, j ), y( j ) ); }
325 
326  PointLonLat lonlat( idx_t i, idx_t j ) const { return projection_.lonlat( xy( i, j ) ); }
327 
328  void lonlat( idx_t i, idx_t j, double crd[] ) const {
329  xy( i, j, crd );
330  projection_.xy2lonlat( crd );
331  }
332 
333  inline bool reduced() const { return nxmax() != nxmin(); }
334 
335  bool periodic() const { return periodic_x_; }
336 
337  const XSpace& xspace() const { return xspace_; }
338  const YSpace& yspace() const { return yspace_; }
339 
340  virtual std::unique_ptr<Grid::IteratorXY> xy_begin() const override {
341  return std::unique_ptr<Grid::IteratorXY>( new IteratorXY( *this ) );
342  }
343  virtual std::unique_ptr<Grid::IteratorXY> xy_end() const override {
344  return std::unique_ptr<Grid::IteratorXY>( new IteratorXY( *this, false ) );
345  }
346  virtual std::unique_ptr<Grid::IteratorLonLat> lonlat_begin() const override {
347  return std::unique_ptr<Grid::IteratorLonLat>( new IteratorLonLat( *this ) );
348  }
349  virtual std::unique_ptr<Grid::IteratorLonLat> lonlat_end() const override {
350  return std::unique_ptr<Grid::IteratorLonLat>( new IteratorLonLat( *this, false ) );
351  }
352 
353  gidx_t index( idx_t i, idx_t j ) const { return jglooff_[j] + i; }
354 
355  void index2ij( gidx_t gidx, idx_t& i, idx_t& j ) const {
356  if ( ( gidx < 0 ) || ( gidx >= jglooff_.back() ) ) {
357  throw_Exception( "Structured::index2ij: gidx out of bounds", Here() );
358  }
359  idx_t ja = 0, jb = jglooff_.size();
360  while ( jb - ja > 1 ) {
361  idx_t jm = ( ja + jb ) / 2;
362  if ( gidx < jglooff_[jm] ) {
363  jb = jm;
364  }
365  else {
366  ja = jm;
367  }
368  }
369  i = gidx - jglooff_[ja];
370  j = ja;
371  }
372 
373  Config meshgenerator() const override;
374  Config partitioner() const override;
375 
376 
377 protected: // methods
378  virtual void print( std::ostream& ) const override;
379 
380  virtual void hash( eckit::Hash& ) const override;
381 
382  virtual RectangularLonLatDomain lonlatBoundingBox() const override;
383 
384  void computeTruePeriodicity();
385 
386  Domain computeDomain() const;
387 
388  void crop( const Domain& );
389 
390 protected:
391  // Minimum number of points across parallels (constant y)
392  idx_t nxmin_;
393 
394  // Maximum number of points across parallels (constant y)
395  idx_t nxmax_;
396 
399 
401  std::vector<double> y_;
402 
404  std::vector<idx_t> nx_;
405 
407  std::vector<double> xmin_;
408 
410  std::vector<double> xmax_;
411 
413  std::vector<double> dx_;
414 
417 
419  std::vector<gidx_t> jglooff_;
420 
421 private:
422  std::string name_ = {"structured"};
423  XSpace xspace_;
424  YSpace yspace_;
425  mutable std::string type_;
426 };
427 
428 extern "C" {
429 void atlas__grid__Structured__delete( Structured* This );
430 const Structured* atlas__grid__Structured( char* identifier );
431 const Structured* atlas__grid__Structured__config( util::Config* conf );
432 Structured* atlas__grid__regular__RegularGaussian( long N );
433 Structured* atlas__grid__reduced__ReducedGaussian_int( int nx[], long ny );
434 Structured* atlas__grid__reduced__ReducedGaussian_long( long nx[], long ny );
435 Structured* atlas__grid__reduced__ReducedGaussian_int_projection( int nx[], long ny,
436  const Projection::Implementation* projection );
437 Structured* atlas__grid__reduced__ReducedGaussian_long_projection( long nx[], long ny,
438  const Projection::Implementation* projection );
439 Structured* atlas__grid__regular__RegularLonLat( long nx, long ny );
440 Structured* atlas__grid__regular__ShiftedLonLat( long nx, long ny );
441 Structured* atlas__grid__regular__ShiftedLon( long nx, long ny );
442 Structured* atlas__grid__regular__ShiftedLat( long nx, long ny );
443 
444 void atlas__grid__Structured__nx_array( Structured* This, const idx_t*& nx, idx_t& size );
445 idx_t atlas__grid__Structured__nx( Structured* This, idx_t j );
446 idx_t atlas__grid__Structured__ny( Structured* This );
447 gidx_t atlas__grid__Structured__index( Structured* This, idx_t i, idx_t j );
448 void atlas__grid__Structured__index2ij( Structured* This, gidx_t gidx, idx_t& i, idx_t& j );
449 idx_t atlas__grid__Structured__nxmin( Structured* This );
450 idx_t atlas__grid__Structured__nxmax( Structured* This );
451 double atlas__grid__Structured__y( Structured* This, idx_t j );
452 double atlas__grid__Structured__x( Structured* This, idx_t i, idx_t j );
453 void atlas__grid__Structured__xy( Structured* This, idx_t i, idx_t j, double crd[] );
454 void atlas__grid__Structured__lonlat( Structured* This, idx_t i, idx_t j, double crd[] );
455 void atlas__grid__Structured__y_array( Structured* This, const double*& lats, idx_t& size );
456 int atlas__grid__Structured__reduced( Structured* This );
457 
458 idx_t atlas__grid__Gaussian__N( Structured* This );
459 }
460 
461 } // namespace grid
462 } // namespace detail
463 } // namespace grid
464 } // namespace atlas
virtual RectangularLonLatDomain lonlatBoundingBox() const override
Definition: Structured.cc:699
std::string hash() const
Definition: Grid.cc:127
Structured Grid.
Definition: Structured.h:39
Definition: Spacing.h:44
double max() const
Value of maximum x over entire grid.
Definition: Structured.h:264
This file contains classes and functions working on points.
virtual void print(std::ostream &) const override
Fill provided me.
Definition: Structured.cc:645
Point in longitude-latitude coordinate system.
Definition: Point.h:103
Definition: Projection.h:49
bool periodic_x_
Periodicity in x-direction.
Definition: Structured.h:416
const std::vector< double > & dx() const
Value of longitude increment.
Definition: Structured.h:258
const Projection & projection() const
Definition: Grid.h:113
virtual std::string name() const override
Human readable name Either the name is the one given at construction as a canonical named grid...
Definition: Structured.cc:44
Definition: Domain.h:130
const std::vector< double > & xmin() const
Value of minimum longitude per latitude [default=0].
Definition: Structured.h:252
std::vector< double > dx_
Value of longitude increment.
Definition: Structured.h:413
std::vector< double > y_
Latitude values.
Definition: Structured.h:401
const std::vector< double > & xmax() const
Value of maximum longitude per latitude [default=0].
Definition: Structured.h:255
Definition: Object.h:18
double min() const
Value of minimum x over entire grid.
Definition: Structured.h:261
std::vector< gidx_t > jglooff_
Per-row offset.
Definition: Structured.h:419
std::vector< double > xmin_
Value of minimum longitude per latitude [default=0].
Definition: Structured.h:407
Definition: Grid.h:42
Definition: Domain.h:48
virtual idx_t size() const override
Definition: Structured.h:286
long gidx_t
Integer type for global indices.
Definition: config.h:34
std::vector< idx_t > nx_
Number of points per latitude.
Definition: Structured.h:404
Point in arbitrary XY-coordinate system.
Definition: Point.h:40
std::vector< double > xmax_
Value of maximum longitude per latitude [default=0].
Definition: Structured.h:410
Contains all atlas classes and methods.
Definition: atlas-grids.cc:33
long idx_t
Integer type for indices in connectivity tables.
Definition: config.h:42
const std::vector< idx_t > & nx() const
Number of points per latitude.
Definition: Structured.h:249
Configuration class used to construct various atlas components.
Definition: Config.h:27
idx_t npts_
Total number of unique points in the grid.
Definition: Structured.h:398