35c6fbdcf5c23aed79acf30c8d5a89c3c44ccf61
[charm.git] / src / libs / ck-libs / mblock / mblock_impl.h
1 /*Charm++ Multiblock CFD Framework:
2 C++ implementation file
3
4 This is the under-the-hood implementation file for MBLOCK.
5 Milind Bhandarkar
6 */
7 #ifndef _MBLOCK_IMPL_H
8 #define _MBLOCK_IMPL_H
9
10 #include <stdio.h>
11
12 #include "mblock.decl.h"
13 #include "mblock.h"
14 #include "patch.h"
15 #include "charm-api.h"
16 #include "tcharm.h"
17 #include "tcharmc.h"
18
19 #define CHK(p) do{if((p)==0)CkAbort("MBLK>Memory Allocation failure.");}while(0)
20
21 // temporary Datatype representation
22 // will go away once MPI user-defined datatypes are ready
23 struct DType {
24   int base_type;
25   int vec_len;
26   int init_offset; // offset of field in bytes from the beginning of data
27   int distance; // distance in bytes between successive field values
28   DType(void) {}
29   DType(const DType& dt) : 
30     base_type(dt.base_type), vec_len(dt.vec_len), init_offset(dt.init_offset),
31     distance(dt.distance) {}
32   void operator=(const DType& dt) {
33     base_type = dt.base_type; 
34     vec_len = dt.vec_len; 
35     init_offset = dt.init_offset;
36     distance = dt.distance;
37   }
38   DType( const int b,  const int v=1,  const int i=0,  const int d=0) : 
39     base_type(b), vec_len(v), init_offset(i) {
40     distance = (d ? d : length());
41   }
42   int length(const int nitems=1) const {
43     int blen;
44     switch(base_type) {
45       case MBLK_BYTE : blen = 1; break;
46       case MBLK_INT : blen = sizeof(int); break;
47       case MBLK_REAL : blen = sizeof(float); break;
48       case MBLK_DOUBLE : blen = sizeof(double); break;
49     }
50     return blen * vec_len * nitems;
51   }
52
53   void pup(PUP::er &p) {
54     p(base_type);
55     p(vec_len);
56     p(init_offset);
57     p(distance);
58   }
59
60 };
61
62 class MBlockDataMsg : public CMessage_MBlockDataMsg
63 {
64  public:
65   int seqnum;
66   int from;
67   int fid;
68   unsigned char *data;
69   int patchno;
70   MBlockDataMsg(int s, int f, int fid_, int p) : 
71     seqnum(s), from(f), fid(fid_), patchno(p) {  }
72 };
73
74 #define MBLK_MAXDT 20
75 #define MBLK_MAXUDATA 20
76 #define MBLK_MAXBC 20
77
78 class field_t {
79  public:
80   DType dt; //Describes 1D data layout
81   blockDim dim; //User-allocated dimensions of field
82   int arrayBytes; //Bytes in user-allocated array
83   bool forVoxel; //Field is for a voxel, not a node attribute
84   field_t(const DType &dt_,const blockDim &dim_,bool forVoxel_)
85     :dt(dt_),dim(dim_),forVoxel(forVoxel_) {
86     arrayBytes=dim.getSize()*dt.distance;
87   }
88
89   field_t() { }
90   void pup(PUP::er &p) {
91     dt.pup(p);
92     dim.pup(p);
93     p(forVoxel);
94   }
95 };
96
97 class MBlockChunk: public CBase_MBlockChunk
98 {
99 private:
100   int nfields;
101   field_t *fields[MBLK_MAXDT];
102
103   int nudata;
104   void *userdata[MBLK_MAXUDATA];
105   MBLK_PupFn pup_ud[MBLK_MAXUDATA];
106
107   CProxy_TCharm threads;
108   TCharm *thread;
109
110   class bc_t {
111   public:
112     MBLK_BcFn fn;
113     extrudeMethod m;
114     bool isFortran;
115   };
116   bc_t bcs[MBLK_MAXBC];
117
118   CmmTable messages; // messages for updates yet to be initiated
119   int seqnum; //Number of most recently initiated update
120   class update_t {
121   public:
122     int nRecd; //Number of messages received so far
123     extrudeMethod m;
124     int wait_seqnum; // update # that we ar waiting for, -1 if not waiting
125     void *ogrid; // grid pointer for receiving updates
126   };
127   update_t update;
128   int nRecvPatches;  //Number of messages to expect (a constant)
129
130   void *reduce_output;//Result of reduction goes here
131
132   void commonInit(void);
133   void migInit(void);
134  public:
135   block *b;
136
137   MBlockChunk(const CkArrayID &threads);
138   MBlockChunk(CkMigrateMessage *msg);
139   ~MBlockChunk();
140   
141   void read(const char *prefix,int nDim);
142   
143   void ckJustMigrated(void);
144   
145   //entry methods
146   void recv(MBlockDataMsg *);
147   void reductionResult(CkReductionMsg *);
148
149   int add_field(field_t *f) {
150     if (nfields==MBLK_MAXDT) return -1;
151     fields[nfields]=f;
152     nfields++;
153     return nfields-1;
154   }
155
156   void start_update(int fid,const extrudeMethod &m,void *ingrid, void *outgrid);
157   int test_update(void);
158   int wait_update(void);
159   void reduce_field(int fid, const void *nodes, void *outbuf, int op);
160   void reduce(int fid, const void *inbuf, void *outbuf, int op);
161   void print(void);
162
163   int register_bc(const int bcnum, const MBLK_BcFn bcfn,const extrudeMethod &m,bool isFortran)
164   {
165     if(bcnum<0 || bcnum>=MBLK_MAXBC) {
166       CkError("MBLK> BC index should be between 0 and %d!\n", MBLK_MAXBC-1);
167       return MBLK_FAILURE;
168     }
169     bcs[bcnum].fn = bcfn;
170     bcs[bcnum].m=m;
171     bcs[bcnum].isFortran=isFortran;
172     return MBLK_SUCCESS;
173   }
174
175   void apply_single_bc(patch *p,void *p1,void *p2) {
176     int bcNo=((externalBCpatch *)p)->bcNo;
177     blockSpan s=p->getExtents(bcs[bcNo].m,true);
178     int start[3],end[3];
179     if (bcs[bcNo].isFortran) { //Switch to 1-based indexing
180       s.start=s.start+blockLoc(1,1,1);
181       s.end=s.end+blockLoc(1,1,1);
182     }
183     s.getInt3(start,end);
184     thread->activateHeap();
185     (bcs[bcNo].fn)(p1,p2,start,end);
186     thread->deactivateHeap();
187   }
188
189   int apply_bc(const int bcnum, void *p1,void *p2)
190   {
191     if(bcs[bcnum].fn == 0) {
192       CkError("MBLK> BC handler not registered for bcnum %d!\n", bcnum);
193       return MBLK_FAILURE;
194     }
195     int n = b->getPatches();
196     for (int i=0; i< n; i++) {
197       patch *p = b->getPatch(i);
198       if(p->type == patch::ext && ((externalBCpatch*)p)->bcNo == bcnum) 
199         apply_single_bc(p,p1,p2);
200     }
201     return MBLK_SUCCESS;
202   }
203
204   int apply_bc_all(void *p1,void *p2)
205   {
206     int i;
207     int n = b->getPatches();
208     for(i=0;i<n;i++) {
209       patch *p = b->getPatch(i);
210       if(p->type == patch::ext)
211         apply_single_bc(p,p1,p2);      
212     }
213     return MBLK_SUCCESS;
214   }
215
216   static void copy(const blockLoc &src,int *dest,int shift=0) {
217     dest[0]=src[0]+shift; dest[1]=src[1]+shift; dest[2]=src[2]+shift;
218   }
219
220   void pup(PUP::er &p);
221
222  private:
223   void send(int fid,const extrudeMethod &m,const void *grid);
224   void update_field(MBlockDataMsg *m);
225 };
226
227 class MBlockSetupCookie
228 {
229  public:
230   MBlockSetupCookie();
231   char prefix[1024];
232   int ndims;
233   int nblocks;
234   void createArray(void);
235 };
236
237 #define MBLOCKAPI(routineName) TCHARM_API_TRACE(routineName,"mblock")
238
239 #endif
240
241