1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#ifndef GS_HPP
#define GS_HPP

#include "moab/MOABConfig.h"
#include "moab/TupleList.hpp"
#include "moab/Types.hpp"

#ifdef MOAB_HAVE_MPI
#include "moab_mpi.h"
#endif

namespace moab
{

class gs_data
{
  public:
#ifdef MOAB_HAVE_MPI
    class nonlocal_info
    {
      public:
        uint _np;           /* number of processors to communicate with          */
        uint* _target;      /* int target[np]: array of processor ids to comm w/ */
        uint* _nshared;     /* nshared[i] = number of points shared w/ target[i] */
        uint* _sh_ind;      /* list of shared point indices                      */
        slong* _slabels;    /* list of signed long labels (not including gid)    */
        Ulong* _ulabels;    /* list of unsigned long labels                      */
        MPI_Request* _reqs; /* pre-allocated for MPI calls                       */
        realType* _buf;     /* pre-allocated buffer to receive data              */
        uint _maxv;         /* maximum vector size                               */

        /**Constructor for nonlocal_info; takes all arguments and initializes
         * nonlocal_info
         *
         * param np        number of processors to communicate with
         * param count     number of partner processors
         * param nlabels   number of signed long labels (not including gid)
         * param nulabels  number of unsigned long labels
         * param maxv      maximum vector size
         */
        nonlocal_info( uint tmp_np, uint count, uint nlabels, uint nulabels, uint tmp_maxv )
        {
            this->initialize( tmp_np, count, nlabels, nulabels, tmp_maxv );
        }

        /**Initializes nonlocal_info; see constructor for parameter documentation
         */
        void initialize( uint np, uint count, uint nlabels, uint nulabels, uint maxv );

        ~nonlocal_info()
        {
            nlinfo_free();
        };

        void nonlocal( realType* u, int op, MPI_Comm comm );
        void nonlocal_vec( realType* u, uint n, int op, MPI_Comm comm );
        void nonlocal_many( realType** u, uint n, int op, MPI_Comm comm );
        void nlinfo_free();
    };

  public:
    /*---------------------------------------------------------------------------

      Crystal Router

      Accomplishes all-to-all communication in log P msgs per proc
      The routine is low-level; the format of the input/output is an
      array of integers, consisting of a sequence of messages with format:

      target proc
      source proc
      m
      integer
      integer
      ...
      integer  (m integers in total)

      Before moab_crystal_router is called, the source of each message should be
      set to this proc id; upon return from moab_crystal_router, the target of each
      message will be this proc id.

      Usage:

      MPI_Comm comm = ... ;
      moab_crystal_data crystal;
      //moab_crystal_data crystal(comm);  //or this to initialize on
      //instantiation

      crystal.initialize(comm);  // initialize the data structure
      // now crystal.id  = this proc
      // and crystal.num = num of procs

      // allocate space for at least MAX ints
      buffer_reserve(&crystal->all->buf, MAX*sizeof(uint));

      // fill up ((uint*)crystal->all->buf.ptr)[0 ... n-1]
      // and set crystal->all->n

      crystal.moab_crystal_router();

      // incoming messages available as
      // ((uint*)crystal->all->buf.ptr)[0 ... crystal->all->n-1]

      crystal.reset(); // release acquired memory

      ---------------------------------------------------------------------------*/

    class crystal_data
    {
      public:
        // moab_crystal_data member variables & data
        typedef struct
        {
            uint n;
            moab::TupleList::buffer buf;
        } crystal_buf;
        crystal_buf buffers[3];
        // crystal_buf provides buffer space for communications
        crystal_buf *all, *keep, *send;
        MPI_Comm _comm;
        uint _num, _id;

        /**Default constructor (Note:  moab_crystal_data must be initialized
         * before use!)
         */
        crystal_data();

        /**Constructor takes an MPI_Comm and initializes the moab_data_crystal
         */
        crystal_data( MPI_Comm cm )
        {
            initialize( cm );
        };

        ~crystal_data()
        {
            reset();
        };

        /**Initializes crystal_data members according to MPI_Comm passed in
         * Note:  moab_crystal_data must be initialized before it can be used
         *
         * param comm  MPI_Comm detailing where to send messages
         */
        void initialize( MPI_Comm comm );

        /**Frees buffers used by moab_crystal_data
         */
        void reset();

        /**Communicates messages with other processors; see class description for
         * more info and usage
         */
        void crystal_router();

        /**Treats one integer (not long) member of the TupleList as a target proc;
         * Sends out tuples accordingly, using the crystal router.
         * Target proc member overwritten with source proc.
         *
         * param dynamic   non-zero if the TupleList should grow to accomodate
         *                 arrivals
         * param tl        the TupleList
         * param pf        which tuple member specifies target proc
         */
        ErrorCode gs_transfer( int dynamic, moab::TupleList& tl, unsigned pf );

      private:
        // Used by moab_crystal_router:  see .cpp for more details
        void partition( uint cutoff, crystal_buf* lo, crystal_buf* hi );

        void send_( uint target, int recvn );
    };
#else
    // If mpi is not used, moab_crystal_data cannot be used
    class crystal_data
    {
    };
#endif

    sint* local_cm; /* local condense map */
#ifdef MOAB_HAVE_MPI
    nonlocal_info* nlinfo;
    MPI_Comm _comm;
#endif

    /**Constructor for moab_gs_data:  takes all arguments and initializes
     * moab_gs_data.  If needs_reset is false after calling constructor,
     * initialization has failed.
     *
     * param n         number of tuples in tuple list
     * param label     pointer to signed labels
     * param ulabel    pointer to unsigned labels
     * param maxv      max vector size
     * param nlabels   number of signed long labels (not including gid)
     * param nulabels  number of unsigned long labels
     * param crystal   moab_crystal_data contains MPI_Comm and is used for
     *                 message passing
     */
    gs_data( uint n,
             const long* label,
             const Ulong* ulabel,
             uint maxv,
             const unsigned int nlabels,
             const unsigned int nulabels,
             crystal_data* crystal,
             ErrorCode& Init_Result )
    {
        Init_Result = this->initialize( n, label, ulabel, maxv, nlabels, nulabels, crystal );
    };

    /**Default constructor (Note:  moab_gs_data must be initialized
     * before use!)
     */
    gs_data(){};

    ~gs_data()
    {
        reset();
    }

    /**Sets up the moab_gs_data; see constructor for parameter documentation
     */
    ErrorCode initialize( uint n,
                          const long* label,
                          const Ulong* ulabel,
                          uint maxv,
                          const unsigned int nlabels,
                          const unsigned int nulabels,
                          crystal_data* crystal );

    void reset();

    void gs_data_op( realType* u, int op );
    void gs_data_op_vec( realType* u, uint n, int op );
    void gs_data_op_many( realType** u, uint n, int op );

#define GS_OP_ADD 1
#define GS_OP_MUL 2
#define GS_OP_MIN 3
#define GS_OP_MAX 4
#define GS_OP_BPR 5
};

}  // namespace moab
#endif