atlas
Connectivity.h
Go to the documentation of this file.
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 
24 
25 #pragma once
26 
27 #include <array>
28 #include <cstring>
29 #include <initializer_list>
30 
31 #include "atlas/array.h"
32 #include "atlas/array/ArrayView.h"
33 #include "atlas/array/DataType.h"
34 #include "atlas/array/IndexView.h"
35 #include "atlas/array/SVector.h"
36 #include "atlas/array/Vector.h"
37 #include "atlas/array_fwd.h"
38 #include "atlas/library/config.h"
39 #include "atlas/util/Object.h"
40 
41 namespace eckit {
42 class Stream;
43 }
44 
45 namespace atlas {
46 namespace mesh {
47 
48 constexpr size_t MAX_STRING_SIZE() {
49  return 60;
50 }
51 
52 template <typename ConnectivityImpl>
53 class ConnectivityInterface : public util::Object, DOXYGEN_HIDE( public ConnectivityImpl ) {
54  using ConnectivityImpl::ConnectivityImpl;
55  using util::Object::Object;
56 };
57 
58 // Classes defined in this file:
62 
63 // --------------------------------------------------------------------------
64 
65 #ifndef DOXYGEN_SHOULD_SKIP_THIS
66 #if ATLAS_HAVE_FORTRAN
67 #define INDEX_DEREF Index
68 #define INDEX_REF Index
69 #define FROM_FORTRAN -1
70 #define TO_FORTRAN +1
71 #else
72 #define INDEX_DEREF *
73 #define INDEX_REF idx_t&
74 #define FROM_FORTRAN
75 #define TO_FORTRAN
76 #endif
77 #endif
78 
101 
102 namespace detail {
103 // FortranIndex:
104 // Helper class that does +1 and -1 operations on stored values
105 
107 public:
108  enum
109  {
110  BASE = 1
111  };
112 
113 public:
114  ATLAS_HOST_DEVICE ConnectivityIndex( const ConnectivityIndex& other ) { set( other.get() ); }
115  ATLAS_HOST_DEVICE ConnectivityIndex( idx_t* idx ) : idx_( idx ) {}
116  ATLAS_HOST_DEVICE void set( const idx_t& value ) { *( idx_ ) = value + BASE; }
117  ATLAS_HOST_DEVICE idx_t get() const { return *(idx_)-BASE; }
118  ATLAS_HOST_DEVICE void operator=( const idx_t& value ) { set( value ); }
119  ATLAS_HOST_DEVICE ConnectivityIndex& operator+( const idx_t& value ) {
120  *( idx_ ) += value;
121  return *this;
122  }
123  ATLAS_HOST_DEVICE ConnectivityIndex& operator-( const idx_t& value ) {
124  *( idx_ ) -= value;
125  return *this;
126  }
127  ATLAS_HOST_DEVICE ConnectivityIndex& operator--() {
128  --( *( idx_ ) );
129  return *this;
130  }
131  ATLAS_HOST_DEVICE ConnectivityIndex& operator++() {
132  ++( *( idx_ ) );
133  return *this;
134  }
135 
136  // implicit conversion
137  ATLAS_HOST_DEVICE operator idx_t() const { return get(); }
138 
139 private:
140  idx_t* idx_;
141 };
142 } // namespace detail
143 
145 #if ATLAS_HAVE_FORTRAN
146  using Index = detail::ConnectivityIndex;
147 #else
148  using Index = idx_t&;
149 #endif
150 public:
151  ATLAS_HOST_DEVICE
152  ConnectivityRow( idx_t* data, idx_t size ) : data_( data ), size_( size ) {}
153 
154  template <typename Int>
155  ATLAS_HOST_DEVICE idx_t operator()( Int i ) const {
156  return data_[i] FROM_FORTRAN;
157  }
158 
159  template <typename Int>
160  ATLAS_HOST_DEVICE INDEX_REF operator()( Int i ) {
161  return INDEX_DEREF( data_ + i );
162  }
163 
164  ATLAS_HOST_DEVICE
165  idx_t size() const { return size_; }
166 
167 private:
168  idx_t* data_;
169  idx_t size_;
170 };
171 
173 public:
174  typedef ConnectivityRow Row;
175 
176 public:
177  //-- Constructors
178 
181  IrregularConnectivityImpl( const std::string& name = "" );
182 
185  IrregularConnectivityImpl( idx_t values[], idx_t rows, idx_t displs[], idx_t counts[] );
186 
187 #ifdef __CUDACC__
188  // This ctr has to be defined in the header, since __CUDACC__ will identify
190  // whether
191  // it is compiled it for a GPU kernel
193  owns_( false ),
194  values_( other.values_ ),
195  displs_( other.displs_ ),
196  counts_( other.counts_ ),
197  missing_value_( other.missing_value_ ),
198  rows_( other.rows_ ),
199  maxcols_( other.maxcols_ ),
200  mincols_( other.mincols_ ),
201  ctxt_( nullptr ) {}
202 #endif
203 
205  explicit IrregularConnectivityImpl( eckit::Stream& );
206 
207  virtual ~IrregularConnectivityImpl();
208 
209  //-- Accessors
210 
212  const std::string name() const { return std::string( name_ ); }
213 
215  void rename( const std::string& name ) {
216  std::strncpy( name_, name.c_str(), std::max( name.size(), MAX_STRING_SIZE() ) );
217  }
218 
220  ATLAS_HOST_DEVICE
221  idx_t rows() const { return rows_; }
222 
224  ATLAS_HOST_DEVICE
225  idx_t cols( idx_t row_idx ) const { return counts_[row_idx]; }
226 
228  ATLAS_HOST_DEVICE
229  idx_t maxcols() const { return maxcols_; }
230 
232  ATLAS_HOST_DEVICE
233  idx_t mincols() const { return mincols_; }
234 
237  ATLAS_HOST_DEVICE
238  idx_t operator()( idx_t row_idx, idx_t col_idx ) const;
239 
240  idx_t size() const { return values_.size(); }
241 
242  ATLAS_HOST_DEVICE
243  idx_t missing_value() const { return missing_value_; }
244 
245  ATLAS_HOST_DEVICE
246  Row row( idx_t row_idx ) const;
247 
248  // -- Modifiers
249 
251  void set( idx_t row_idx, const idx_t column_values[] );
252 
254  void set( idx_t row_idx, idx_t col_idx, const idx_t value );
255 
258  virtual void resize( idx_t old_size, idx_t size, bool initialize, const idx_t values[], bool fortran_array );
259 
262  virtual void add( idx_t rows, idx_t cols, const idx_t values[], bool fortran_array = false );
263 
266  virtual void add( idx_t rows, idx_t cols );
267 
270  virtual void add( idx_t rows, const idx_t cols[] );
271 
273  virtual void add( const BlockConnectivityImpl& block );
274 
277  virtual void insert( idx_t position, idx_t rows, idx_t cols, const idx_t values[], bool fortran_array = false );
278 
281  virtual void insert( idx_t position, idx_t rows, idx_t cols );
282 
285  virtual void insert( idx_t position, idx_t rows, const idx_t cols[] );
286 
287  virtual void clear();
288 
289  virtual size_t footprint() const;
290 
291  idx_t displs( const idx_t row ) const { return displs_[row]; }
292 
293  void dump( std::ostream& os ) const;
294  friend std::ostream& operator<<( std::ostream& os, const IrregularConnectivityImpl& p ) {
295  p.dump( os );
296  return os;
297  }
298 
299  virtual void encode( eckit::Stream& s ) const { encode_( s ); }
300  virtual void decode( eckit::Stream& s ) { decode_( s ); }
301 
302 protected:
303  bool owns() { return owns_; }
304  const idx_t* displs() const { return displs_.data(); }
305  const idx_t* counts() const { return counts_.data(); }
306 
308  void encode_( eckit::Stream& ) const;
309 
311  void decode_( eckit::Stream& );
312 
313  friend eckit::Stream& operator<<( eckit::Stream& s, const IrregularConnectivityImpl& x ) {
314  x.encode( s );
315  return s;
316  }
317 
318  friend eckit::Stream& operator>>( eckit::Stream& s, IrregularConnectivityImpl& x ) {
319  x.decode( s );
320  return s;
321  }
322 
323 private:
324  void on_delete();
325  void on_update();
326 
327 private:
328  char name_[MAX_STRING_SIZE()];
329  bool owns_;
330 
331 protected:
332  array::SVector<idx_t> values_;
333  array::SVector<idx_t> displs_;
334  array::SVector<idx_t> counts_;
335 
336  idx_t missing_value_;
337  idx_t rows_;
338  idx_t maxcols_;
339  idx_t mincols_;
340 
341 public:
342  typedef void* ctxt_t;
343  typedef void ( *callback_t )( ctxt_t );
344 
345 private:
346  friend class ConnectivityPrivateAccess;
347  ctxt_t ctxt_;
348  callback_t callback_update_;
349  callback_t callback_delete_;
350 };
351 
352 // ----------------------------------------------------------------------------------------------
353 
389 public:
390  //-- Constructors
391 
394  MultiBlockConnectivityImpl( const std::string& name = "" );
395 
397  explicit MultiBlockConnectivityImpl( eckit::Stream& );
398 
399  virtual ~MultiBlockConnectivityImpl();
400 
401  //-- Accessors
402 
404  ATLAS_HOST_DEVICE
405  idx_t blocks() const { return blocks_; }
406 
408  ATLAS_HOST_DEVICE
409  const BlockConnectivityImpl& block( idx_t block_idx ) const { return block_[block_idx]; }
410  ATLAS_HOST_DEVICE
411  BlockConnectivityImpl& block( idx_t block_idx ) { return block_[block_idx]; }
412 
416  ATLAS_HOST_DEVICE
417  idx_t operator()( idx_t row_idx, idx_t col_idx ) const;
418 
422  ATLAS_HOST_DEVICE
423  idx_t operator()( idx_t block_idx, idx_t block_row_idx, idx_t block_col_idx ) const;
424 
425  //-- Modifiers
426 
429  virtual void add( idx_t rows, idx_t cols, const idx_t values[], bool fortran_array = false );
430 
434  virtual void add( const BlockConnectivityImpl& );
435 
438  virtual void add( idx_t rows, idx_t cols );
439 
442  virtual void add( idx_t rows, const idx_t cols[] );
443 
446  virtual void insert( idx_t position, idx_t rows, idx_t cols, const idx_t values[], bool fortran_array = false );
447 
450  virtual void insert( idx_t position, idx_t rows, idx_t cols );
451 
454  virtual void insert( idx_t position, idx_t rows, const idx_t cols[] );
455 
456  virtual void clear();
457 
458  virtual size_t footprint() const;
459 
460  virtual void encode( eckit::Stream& s ) const {
461  IrregularConnectivityImpl::encode_( s );
462  encode_( s );
463  }
464  virtual void decode( eckit::Stream& s ) {
465  IrregularConnectivityImpl::decode_( s );
466  decode_( s );
467  }
468 
469 protected:
471  void encode_( eckit::Stream& ) const;
472 
474  void decode_( eckit::Stream& );
475 
476  friend eckit::Stream& operator<<( eckit::Stream& s, const MultiBlockConnectivityImpl& x ) {
477  x.encode( s );
478  return s;
479  }
480 
481  friend eckit::Stream& operator>>( eckit::Stream& s, MultiBlockConnectivityImpl& x ) {
482  x.decode( s );
483  return s;
484  }
485 
486 private:
487  void rebuild_block_connectivity();
488 
489 private:
490  idx_t blocks_;
491  array::SVector<idx_t> block_displs_;
492  array::SVector<idx_t> block_cols_;
493 
495 };
496 
497 // -----------------------------------------------------------------------------------------------------
498 
516 private:
517  friend class IrregularConnectivityImpl;
518  friend class MultiBlockConnectivityImpl;
519  BlockConnectivityImpl( idx_t rows, idx_t cols, idx_t values[], bool dummy );
520 
521 public:
522  //-- Constructors
523 
527  BlockConnectivityImpl( idx_t rows, idx_t cols, const std::initializer_list<idx_t>& );
528 
531  BlockConnectivityImpl( idx_t rows, idx_t cols, idx_t values[] );
532 
533 #ifdef __CUDACC__
534  // This ctr has to be defined in the header, since __CUDACC__ will identify
536  // whether it is compiled it for a GPU kernel
538  owns_( false ),
539  values_( other.values_ ),
540  rows_( other.rows_ ),
541  cols_( other.cols_ ),
542  missing_value_( other.missing_value_ ) {}
543 #endif
544 
546 
547  BlockConnectivityImpl& operator=( const BlockConnectivityImpl& other );
548  BlockConnectivityImpl& operator=( BlockConnectivityImpl&& other );
549 
551  explicit BlockConnectivityImpl( eckit::Stream& );
552 
555 
556  ATLAS_HOST_DEVICE
557  idx_t index( idx_t i, idx_t j ) const;
558 
559  //-- Accessors
560 
563  ATLAS_HOST_DEVICE
564  idx_t operator()( idx_t row_idx, idx_t col_idx ) const;
565 
567  ATLAS_HOST_DEVICE
568  idx_t rows() const { return rows_; }
569 
571  ATLAS_HOST_DEVICE
572  idx_t cols() const { return cols_; }
573 
577  ATLAS_HOST_DEVICE
578  const idx_t* data() const { return values_.data(); }
579  ATLAS_HOST_DEVICE
580  idx_t* data() { return values_.data(); }
581 
582  ATLAS_HOST_DEVICE
583  idx_t missing_value() const { return missing_value_; }
584 
585  size_t footprint() const;
586 
587  //-- Modifiers
588 
590  ATLAS_HOST_DEVICE
591  void set( idx_t row_idx, const idx_t column_values[] );
592 
594  ATLAS_HOST_DEVICE
595  void set( idx_t row_idx, idx_t col_idx, const idx_t value );
596 
599  void add( idx_t rows, idx_t cols, const idx_t values[], bool fortran_array = false );
600 
601  bool owns() const { return owns_; }
602 
603 
604  friend std::ostream& operator<<( std::ostream& out, const BlockConnectivityImpl& x ) {
605  x.print( out );
606  return out;
607  }
608 
609 
610 protected:
612  void rebuild( idx_t rows, idx_t cols, idx_t values[] );
613 
614 
616  void encode( eckit::Stream& ) const;
617 
619  void decode( eckit::Stream& );
620 
621  friend eckit::Stream& operator<<( eckit::Stream& s, const BlockConnectivityImpl& x ) {
622  x.encode( s );
623  return s;
624  }
625 
626  friend eckit::Stream& operator>>( eckit::Stream& s, BlockConnectivityImpl& x ) {
627  x.decode( s );
628  return s;
629  }
630 
631  void print( std::ostream& ) const;
632 
633 private:
634  bool owns_;
635  array::SVector<idx_t> values_;
636 
637  idx_t rows_;
638  idx_t cols_;
639  idx_t missing_value_;
640 };
641 
646 
647 // -----------------------------------------------------------------------------------------------------
648 
649 inline idx_t IrregularConnectivityImpl::operator()( idx_t row_idx, idx_t col_idx ) const {
650  assert( counts_[row_idx] > ( col_idx ) );
651  return values_[displs_[row_idx] + col_idx] FROM_FORTRAN;
652 }
653 
654 inline void IrregularConnectivityImpl::set( idx_t row_idx, const idx_t column_values[] ) {
655  const idx_t N = counts_[row_idx];
656  for ( idx_t n = 0; n < N; ++n ) {
657  values_[displs_[row_idx] + n] = column_values[n] TO_FORTRAN;
658  }
659 }
660 
661 inline void IrregularConnectivityImpl::set( idx_t row_idx, idx_t col_idx, const idx_t value ) {
662  assert( col_idx < counts_[row_idx] );
663  values_[displs_[row_idx] + col_idx] = value TO_FORTRAN;
664 }
665 
666 inline IrregularConnectivityImpl::Row IrregularConnectivityImpl::row( idx_t row_idx ) const {
667  return IrregularConnectivityImpl::Row( const_cast<idx_t*>( values_.data() ) + displs_( row_idx ),
668  counts_( row_idx ) );
669 }
670 
671 // -----------------------------------------------------------------------------------------------------
672 
673 inline idx_t MultiBlockConnectivityImpl::operator()( idx_t row_idx, idx_t col_idx ) const {
674  return IrregularConnectivityImpl::operator()( row_idx, col_idx );
675 }
676 
677 inline idx_t MultiBlockConnectivityImpl::operator()( idx_t block_idx, idx_t block_row_idx, idx_t block_col_idx ) const {
678  return block( block_idx )( block_row_idx, block_col_idx );
679 }
680 
681 // -----------------------------------------------------------------------------------------------------
682 
683 inline idx_t BlockConnectivityImpl::operator()( idx_t row_idx, idx_t col_idx ) const {
684  return values_[index( row_idx, col_idx )] FROM_FORTRAN;
685 }
686 
687 inline void BlockConnectivityImpl::set( idx_t row_idx, const idx_t column_values[] ) {
688  for ( idx_t n = 0; n < cols_; ++n ) {
689  values_[index( row_idx, n )] = column_values[n] TO_FORTRAN;
690  }
691 }
692 
693 inline void BlockConnectivityImpl::set( idx_t row_idx, idx_t col_idx, const idx_t value ) {
694  values_[index( row_idx, col_idx )] = value TO_FORTRAN;
695 }
696 
697 inline idx_t BlockConnectivityImpl::index( idx_t i, idx_t j ) const {
698  return i * cols_ + j;
699 }
700 
701 // ------------------------------------------------------------------------------------------------------
702 
703 extern "C" {
704 Connectivity* atlas__Connectivity__create();
705 MultiBlockConnectivity* atlas__MultiBlockConnectivity__create();
706 const char* atlas__Connectivity__name( Connectivity* This );
707 void atlas__Connectivity__rename( Connectivity* This, const char* name );
708 void atlas__Connectivity__delete( Connectivity* This );
709 void atlas__Connectivity__displs( Connectivity* This, idx_t*& displs, idx_t& size );
710 void atlas__Connectivity__counts( Connectivity* This, idx_t*& counts, idx_t& size );
711 void atlas__Connectivity__values( Connectivity* This, idx_t*& values, idx_t& size );
712 idx_t atlas__Connectivity__rows( const Connectivity* This );
713 void atlas__Connectivity__add_values( Connectivity* This, idx_t rows, idx_t cols, idx_t values[] );
714 void atlas__Connectivity__add_missing( Connectivity* This, idx_t rows, idx_t cols );
715 idx_t atlas__Connectivity__missing_value( const Connectivity* This );
716 
717 idx_t atlas__MultiBlockConnectivity__blocks( const MultiBlockConnectivity* This );
718 BlockConnectivityImpl* atlas__MultiBlockConnectivity__block( MultiBlockConnectivity* This, idx_t block_idx );
719 
720 idx_t atlas__BlockConnectivity__rows( const BlockConnectivityImpl* This );
721 idx_t atlas__BlockConnectivity__cols( const BlockConnectivityImpl* This );
722 idx_t atlas__BlockConnectivity__missing_value( const BlockConnectivityImpl* This );
723 void atlas__BlockConnectivity__data( BlockConnectivityImpl* This, idx_t*& data, idx_t& rows, idx_t& cols );
724 void atlas__BlockConnectivity__delete( BlockConnectivityImpl* This );
725 }
726 
727 #undef FROM_FORTRAN
728 #undef TO_FORTRAN
729 #undef INDEX_DEREF
730 
731 //------------------------------------------------------------------------------------------------------
732 
733 } // namespace mesh
734 
735 namespace array {
736 
737 // TODO HACK
738 // template<> inline DataType::kind_t
739 // DataType::kind<mesh::BlockConnectivityImpl*>() { return KIND_INT32; }
740 }
741 
742 } // namespace atlas
void rename(const std::string &name)
Rename this Connectivity.
Definition: Connectivity.h:215
Definition: Connectivity.cc:821
This file contains the IndexView class, a class that allows to wrap any contiguous raw data into a vi...
This file contains the ArrayView class, a class that allows to wrap any contiguous raw data into a vi...
Definition: Connectivity.h:53
void decode(eckit::Stream &)
Serialization from Stream.
Definition: Connectivity.cc:801
Definition: Object.h:18
Definition: Domain.h:19
ATLAS_HOST_DEVICE idx_t blocks() const
Number of blocks.
Definition: Connectivity.h:405
ATLAS_HOST_DEVICE idx_t cols() const
Number of columns.
Definition: Connectivity.h:572
ATLAS_HOST_DEVICE idx_t rows() const
Number of rows in the connectivity table.
Definition: Connectivity.h:221
void encode(eckit::Stream &) const
Serialization to Stream.
Definition: Connectivity.cc:794
ATLAS_HOST_DEVICE idx_t mincols() const
Minimum value for number of columns over all rows.
Definition: Connectivity.h:233
ATLAS_HOST_DEVICE idx_t cols(idx_t row_idx) const
Number of columns for specified row in the connectivity table.
Definition: Connectivity.h:225
ATLAS_HOST_DEVICE const BlockConnectivityImpl & block(idx_t block_idx) const
Access to a block connectivity.
Definition: Connectivity.h:409
Definition: Connectivity.h:144
ATLAS_HOST_DEVICE idx_t rows() const
Number of rows.
Definition: Connectivity.h:568
Block Connectivity table.
Definition: Connectivity.h:515
ATLAS_HOST_DEVICE idx_t maxcols() const
Maximum value for number of columns over all rows.
Definition: Connectivity.h:229
Definition: Connectivity.h:106
Connectivity contiguously composed of multiple BlockConnectivityImpl.
Definition: Connectivity.h:388
const std::string name() const
Name associated to this Connetivity.
Definition: Connectivity.h:212
Forward declarations of public API header atlas/array.h.
Contains all atlas classes and methods.
Definition: atlas-grids.cc:33
ATLAS_HOST_DEVICE const idx_t * data() const
Access to raw data.
Definition: Connectivity.h:578
Definition: Connectivity.h:172
long idx_t
Integer type for indices in connectivity tables.
Definition: config.h:42