f2699394708acfd4790d0f1aa3d4bd50f9d70680
[charm.git] / src / libs / ck-libs / ParFUM / ParFUM_Mesh_Modify.h
1 /* File: fem_mesh_modify.h
2  * Authors: Nilesh Choudhury
3  * 
4  */
5
6 /**
7 This file contains a set of functions, which allow primitive operations upon meshes in parallel. The functions are defined in fem_mesh_modify.C.
8
9 Assumptions:
10
11 The mesh must be in a consistant state before and after these operations:
12 - Any shared node must be in the IDXL table for both the local and 
13 other chunks.
14 - FEM_add_element can only be called with a set of existing local or shared nodes
15 - The mesh must be nice. Each element may be adjacent to at most one other element per face/edge/tuple
16 - The mesh must have e2e, n2n, and n2e adjacencies computed before any of these functions are called.
17 The calls will maintain the adjacency tables, both remotely and locally.
18 - Exactly one ghost layer exists around all chunks before these modification functions are called. 
19 A ghost element is one that is adjacent to at least one shared node. A ghost node is any non-shared 
20 node adjacent to a ghost element. The e2e adjacencies need not have the same definition for 
21 adjacent elements.
22 */
23
24 #ifndef __ParFUM_Mesh_Modify_H
25 #define __ParFUM_Mesh_Modify_H
26
27 //stupid number for maximum number of chunks, but reasonable enough
28 #define MAX_CHUNK 1000000000
29
30 ///Add a node between some adjacent nodes on this mesh
31 int FEM_add_node(FEM_Mesh *m, int* adjacent_nodes=0, int num_adjacent_nodes=0, int *chunks=0, int numChunks=0, int forceShared=0);
32 ///Remove a node on this mesh
33 void FEM_remove_node(FEM_Mesh *m, int node);
34 ///Add an element on this mesh with this connectivity
35 int FEM_add_element(FEM_Mesh *m, int* conn, int conn_size, int elem_type=0, int chunkNo=-1);
36 ///Remove an element on this mesh
37 int FEM_remove_element(FEM_Mesh *m, int element, int elem_type=0, int permanent=-1);
38 ///Purge the element from this mesh (invalidate entry)
39 int FEM_purge_element(FEM_Mesh *m, int element, int elem_type=0);
40
41 // Internal functions used as helper for the above functions
42 ///Update adjacencies for this new node, and attach a lock to it
43 int FEM_add_node_local(FEM_Mesh *m, bool addGhost=false, bool doLocking=true, bool doAdjacencies=true);
44 ///Get rid of idxl entries for this node and clear adjacencies, invalidate node
45 void FEM_remove_node_local(FEM_Mesh *m, int node);
46 ///Update adjacencies for this element and all surrounding nodes/elements
47 int FEM_add_element_local(FEM_Mesh *m, int *conn, int connSize, int elemType, bool addGhost, bool create_adjacencies=1);
48 ///Clear up the adjacencies
49 void FEM_remove_element_local(FEM_Mesh *m, int element, int etype);
50
51 ///Deprecated: locks all chunks for the nodes and elements specified
52 int FEM_Modify_Lock(FEM_Mesh *m, int* affectedNodes=0, int numAffectedNodes=0, int* affectedElts=0, int numAffectedElts=0, int elemtype=0);
53 ///Deprecated: Unlock all chunks that have been locked by this mesh 
54 int FEM_Modify_Unlock(FEM_Mesh *m);
55 ///Lock this node on this mesh with a read/write lock
56 int FEM_Modify_LockN(FEM_Mesh *m, int nodeId, int readLock);
57 ///Lock the read/write lock for this node on this mesh
58 int FEM_Modify_UnlockN(FEM_Mesh *m, int nodeId, int readLock);
59 ///Reassign the lock on a node when a chunk is losing a node
60 void FEM_Modify_LockAll(FEM_Mesh*m, int nodeId, bool lockall=true);
61 ///Update the lock on this node (by locking the newly formed node: Deprecated
62 void FEM_Modify_LockUpdate(FEM_Mesh*m, int nodeId, bool lockall=true);
63 ///For the newly acquired node, correct the lock by removing superfluous locks: Deprecated
64 void FEM_Modify_correctLockN(FEM_Mesh *m, int nodeId);
65
66 ///Get the data for 'length' indices from 'fem_mesh' for the 'attr' of 'entity' starting at index 'firstItem'
67 void FEM_Mesh_dataP(FEM_Mesh *fem_mesh,int entity,int attr,void *data, int firstItem, int length, int datatype,int width);
68 ///Get the data for 'length' indices from 'fem_mesh' for the 'attr' of 'entity' starting at index 'firstItem'
69 void FEM_Mesh_data_layoutP(FEM_Mesh *fem_mesh,int entity,int attr,void *data, int firstItem, int length, IDXL_Layout_t layout);
70 ///Get the data for 'length' indices from 'fem_mesh' for the 'attr' of 'entity' starting at index 'firstItem'
71 void FEM_Mesh_data_layoutP(FEM_Mesh *fem_mesh,int entity,int attr,void *data, int firstItem,int length, const IDXL_Layout &layout);
72
73 ///Copy the essential attributes for this ghost node from remote chunks
74 void FEM_Ghost_Essential_attributes(FEM_Mesh *m, int coord_attr, int bc_attr, int nodeid);
75
76
77
78 ///Message to initialize 'numChunks' and 'chunkIdx' of femMeshModify on all chunks
79 class femMeshModMsg : public CMessage_femMeshModMsg {
80  public:
81   int numChunks;
82   int myChunk;
83
84   femMeshModMsg() {}
85   
86   femMeshModMsg(int num, int idx) {
87     numChunks = num;
88     myChunk = idx;
89   }
90   
91   ~femMeshModMsg() {}
92 };
93
94 ///A Message to encapsulate a boolean
95 class boolMsg : public CMessage_boolMsg {
96  public:
97   bool b;
98
99   boolMsg(bool bo) {
100     b = bo;
101   }
102
103   ~boolMsg() {}
104 };
105
106 ///A message to encapsulate an integer
107 class intMsg : public CMessage_intMsg {
108  public:
109   int i;
110
111   intMsg(int n) {
112     i = n;
113   }
114
115   ~intMsg(){}
116 };
117
118 ///A message to encapsulate two integers
119 class int2Msg : public CMessage_int2Msg {
120  public:
121   int i, j;
122
123   int2Msg(int m, int n) {
124     i = m;
125     j = n;
126   }
127
128   ~int2Msg(){}
129 };
130
131 ///A message to encapsulate two doubles
132 class double2Msg : public CMessage_double2Msg {
133  public:
134   double i,j;
135
136   double2Msg(double m, double n) {
137     i = m;
138     j = n;
139   }
140
141   ~double2Msg() {}
142 };
143
144 ///A message to encapsulate a mesh pointer and a tcharm pointer
145 class FEMMeshMsg : public CMessage_FEMMeshMsg {
146  public:
147   FEM_Mesh *m;
148   TCharm *t;
149         int meshid;
150
151   FEMMeshMsg(FEM_Mesh *mh, TCharm *t1) {
152     m = mh;
153     t = t1;
154   }
155   FEMMeshMsg(FEM_Mesh *mh, TCharm *t1,int _meshid) {
156     m = mh;
157     t = t1;
158                 meshid = _meshid;
159   }
160
161   ~FEMMeshMsg() {}
162 };
163
164 ///A message to pack all the data needed to tell a remote chunk to add a new node
165 class addNodeMsg : public CMessage_addNodeMsg {
166  public:
167   int chk;
168   int nBetween;
169   int *between;
170   int *chunks;
171   int numChunks;
172   int forceShared;
173
174   ~addNodeMsg() {
175     if(between) {
176       //delete between;
177       //delete chunks;
178     }
179   }
180 };
181
182 ///A message used to tell a remote chunk to add a shared node
183 class sharedNodeMsg : public CMessage_sharedNodeMsg {
184  public:
185   int chk;
186   int nBetween;
187   int *between;
188
189   ~sharedNodeMsg() {
190     //if(between!=NULL) {
191     //delete between;
192     //}
193   }
194 };
195
196 ///A message to tell a remote chunk to remove a shared node
197 class removeSharedNodeMsg : public CMessage_removeSharedNodeMsg {
198  public:
199   int chk;
200   int index;
201 };
202
203 ///A message to tell a remote chunk to add a ghost element (all data is packed)
204 class addGhostElemMsg : public CMessage_addGhostElemMsg {
205  public:
206   int chk;
207   int elemType;
208   int *indices;
209   int *typeOfIndex;
210   int connSize;
211
212   ~addGhostElemMsg() {
213     //if(indices!=NULL) {
214     //delete indices;
215     //}
216     //if(typeOfIndex!=NULL) {
217     //delete typeOfIndex;
218     //}
219   }
220 };
221
222 ///A message to return data about the chunks that share/ghost a node/element
223 class chunkListMsg : public CMessage_chunkListMsg {
224  public:
225   int numChunkList;
226   int *chunkList;
227   int *indexList;
228
229   ~chunkListMsg() {
230     if(numChunkList>0) {
231       //delete chunkList;
232       //delete indexList;
233     }
234   }
235 };
236
237 ///A message to pack all data to tell a remote chunk to add an element
238 class addElemMsg : public CMessage_addElemMsg {
239  public:
240   int chk;
241   int elemtype;
242   int connSize;
243   int *conn;
244   int numGhostIndex;
245   int *ghostIndices;
246
247   ~addElemMsg() {
248     if(conn) {
249       //delete conn;
250     }
251     if(ghostIndices) {
252       //delete ghostIndices;
253     }
254   }
255 };
256
257 ///A message to tell a remote chunk to remove a ghost element and some IDXL list entries
258 class removeGhostElemMsg : public CMessage_removeGhostElemMsg {
259  public:
260   int chk;
261   int elemtype;
262   int elementid;
263   int numGhostIndex;
264   int numGhostRNIndex;
265   int numGhostREIndex;
266   int numSharedIndex;
267   int *ghostIndices;
268   int *ghostRNIndices;
269   int *ghostREIndices;
270   int *sharedIndices;
271
272   ~removeGhostElemMsg() {
273     if(ghostIndices!=NULL) {
274       //   delete ghostIndices;
275       //   delete ghostRNIndices;
276       //    delete ghostREIndices;
277       //    delete sharedIndices;
278     }
279   }
280 };
281
282 ///A message to tell a remote chunk to remove an element
283 class removeElemMsg : public CMessage_removeElemMsg {
284  public:
285   int chk;
286   int elementid;
287   int elemtype;
288   int permanent;
289 };
290
291 ///A message to verify if the IDXL entries for a node/element on one chunk is consistent with another chunk
292 class verifyghostsendMsg : public CMessage_verifyghostsendMsg {
293  public:
294   int fromChk;
295   int sharedIdx;
296   int numchks;
297   int *chunks;
298
299   verifyghostsendMsg() {
300   }
301   
302   ~verifyghostsendMsg() {
303     //if(chunks!=NULL) delete chunks;
304   }
305 };
306
307 ///A message that packs the indices of a bunch of chunks (used for ghost send)
308 class findgsMsg : public CMessage_findgsMsg {
309  public:
310   int numchks;
311   int *chunks;
312   
313   ~findgsMsg() {
314   }
315 };
316
317 ///A message that packs all data for a node/element
318 class entDataMsg : public CMessage_entDataMsg {
319  public:
320   char *data;
321   int datasize;
322   int memsize;
323
324   entDataMsg(int size, int msize) {
325     datasize = size;
326     memsize = msize;
327   }
328 };
329
330 ///A message that packs all attributes for a node
331 class updateAttrsMsg : public CMessage_updateAttrsMsg {
332  public:
333   char *data;
334   int datasize;
335   int fromChk;
336   int sharedIdx;
337   bool isnode;
338   bool isGhost;
339   int elemType;
340
341   updateAttrsMsg(int size) {
342     datasize = size;
343     isnode = false;
344     isGhost = false;
345     elemType = 0;
346   }
347 };
348
349
350
351
352 class FEM_Interpolate;
353
354 ///The shadow array attached to a fem chunk to perform all communication during adaptivity
355 /** This data structure maintains some adaptivity information, along with
356     locks for nodes and idxl lists. It handles all the remote function calls
357     and uses FEM_MUtil to perform most of the operations.
358  */
359 class femMeshModify : public CBase_femMeshModify {
360   friend class FEM_lock;
361   friend class FEM_MUtil;
362   friend class FEM_Mesh;
363   friend class FEM_Interpolate;
364   friend class FEM_Adapt;
365   friend class FEM_AdaptL;
366   friend class FEM_Adapt_Algs;
367
368  public:
369   ///Total number of chunks
370   int numChunks;
371   ///Index of this chunk (the chunk this is attached to)
372   int idx;
373   ///The Tcharm pointer to set it even outside the thread..
374   TCharm *tc;
375   ///The proxy for the current Tcharm object
376   CProxy_TCharm tproxy;
377   ///cross-pointer to the fem mesh on this chunk
378   FEM_Mesh *fmMesh;
379   ///Deprecated: used to lock this chunk
380   FEM_lock *fmLock;
381   ///Set of locks for all nodes on this chunk
382   CkVec<FEM_lockN> fmLockN;
383   ///Set of locks for all idxl lists
384   /** each chunk can have numChunks*5 idxl lists, but numChunks locks. 
385    */
386   CkVec<bool> fmIdxlLock;
387   ///The list of fixed nodes
388   /** this list is populated initially, and never changes (defines shape)
389    */
390   CkVec<int> fmfixedNodes;
391   ///Pointer to the utility object (performs most adaptive utilities)
392   FEM_MUtil *fmUtil;
393   ///Pointer to the object that performs the interpolations
394   FEM_Interpolate *fmInp;
395   ///Deprecated: Pointer to the FEM_Adapt object
396   FEM_Adapt *fmAdapt;
397   ///Pointer to the object that performs the primitive adaptive operations
398   FEM_AdaptL *fmAdaptL;
399   ///Pointer to the object that performs the adaptive algorithms
400   FEM_Adapt_Algs *fmAdaptAlgs;
401
402  public:
403   ///constructor
404   femMeshModify(femMeshModMsg *fm);
405   ///constructor for migration
406   femMeshModify(CkMigrateMessage *m);
407   ///destructor
408   ~femMeshModify();
409
410   ///Pup to transfer this object's data
411   void pup(PUP::er &p);
412   ///This function is overloaded, it is called on this object just after migration
413   void ckJustMigrated(void);
414   ///Set the mesh pointer after the migration
415   void setPointersAfterMigrate(FEM_Mesh *m);
416
417   ///Initialize the mesh pointer for this chunk
418   void setFemMesh(FEMMeshMsg *fm);
419
420   ///Deprecated: Try to lock this node on this chunk (the node index is local to this chunk)
421   intMsg *lockRemoteChunk(int2Msg *i2msg);
422   ///Deprecated: Unlock the node on this chunk (the node index is local to this chunk)
423   intMsg *unlockRemoteChunk(int2Msg *i2msg);
424   ///Try to lock this node on this chunk (receives a shared/ghost index)
425   intMsg *lockRemoteNode(int sharedIdx, int fromChk, int isGhost, int readLock);
426   ///Unlock this node on this chunk (receives a shared/ghost index)
427   intMsg *unlockRemoteNode(int sharedIdx, int fromChk, int isGhost, int readLock);
428
429   ///Get number of chunks
430   int getNumChunks(){return numChunks;}
431   ///Get the index of this chunk
432   int getIdx(){return idx;}
433   ///Get the pointer to the mesh object
434   FEM_Mesh *getfmMesh(){return fmMesh;}
435   ///Deprecated: Get the pointer to the lock-chunk object
436   FEM_lock *getfmLock(){return fmLock;}
437   ///Get the status of the lock for this node
438   FEM_lockN getfmLockN(int nodeid){
439     /*if(!FEM_Is_ghost_index(nodeid)) {
440       return fmLockN[nodeid];
441       } else {
442       return fmgLockN[FEM_To_ghost_index(nodeid)];
443       }*/
444     CkAssert(nodeid < fmLockN.size());
445     return fmLockN[nodeid];
446   }
447   ///Get the pointer to the utility object on this chunk
448   FEM_MUtil *getfmUtil(){return fmUtil;}
449   ///Deprecated: Get the pointer to the primitive operation object
450   FEM_Adapt *getfmAdapt(){return fmAdapt;}
451   ///Get the pointer to the object that encapsulates the primitive adaptive operations
452   FEM_AdaptL *getfmAdaptL(){return fmAdaptL;}
453   ///Get the pointer to the object that encapsulates the adaptive algorithms
454   FEM_Adapt_Algs *getfmAdaptAlgs(){return fmAdaptAlgs;}
455   ///Get the pointer to the interpolate object
456   FEM_Interpolate *getfmInp(){return fmInp;}
457
458   ///Get the list of chunks that share this node
459   chunkListMsg *getChunksSharingGhostNode(int2Msg *);
460
461   ///Add a node on this chunk
462   intMsg *addNodeRemote(addNodeMsg *fm);
463   ///Add a shared node on this chunk
464   void addSharedNodeRemote(sharedNodeMsg *fm);
465   ///Remove a shared node on this chunk
466   void removeSharedNodeRemote(removeSharedNodeMsg *fm);
467   ///Remove a ghost node on this chunk
468   void removeGhostNode(int fromChk, int sharedIdx);
469
470   ///Add a ghost element on this chunk
471   void addGhostElem(addGhostElemMsg *fm);
472   ///Add a local element on this chunk
473   intMsg *addElementRemote(addElemMsg *fm);
474   ///Remove a ghost element on this chunk
475   void removeGhostElem(removeGhostElemMsg *fm);
476   ///Remove a local element on this chunk
477   void removeElementRemote(removeElemMsg *fm);
478
479   ///Acquire this element from 'fromChk'
480   intMsg *eatIntoElement(int fromChk, int sharedIdx);
481   
482   ///Get the owner of the lock for this shared node
483   intMsg *getLockOwner(int fromChk, int sharedIdx);
484   ///Does this chunk send this as a ghost to 'toChk'
485   boolMsg *knowsAbtNode(int fromChk, int toChk, int sharedIdx);
486
487   ///propagate a flip operation across chunks
488   void refine_flip_element_leb(int fromChk, int propElemT, int propNodeT,
489                                int newNodeT, int nbrOpNodeT, int nbrghost,
490                                double longEdgeLen);
491
492   ///add this node to the shared idxl lists for 'fromChk'
493   void addToSharedList(int fromChk, int sharedIdx);
494   ///update the attributes of the node with this data
495   void updateAttrs(updateAttrsMsg *umsg);
496   ///get rid of unnecessary node sends to some chunks for a node
497   void updateghostsend(verifyghostsendMsg *vmsg);
498   ///find the set of chunks where this node should be sent as a ghost
499   findgsMsg *findghostsend(int fromChk, int sharedIdx);
500   ///return the shared index on the ghost send list for chunk 'toChk'
501   intMsg *getIdxGhostSend(int fromChk, int idxshared, int toChk);
502
503   ///Get the coordinates for this node
504   double2Msg *getRemoteCoord(int fromChk, int ghostIdx);
505   ///Get the boundary variable for this node
506   intMsg *getRemoteBound(int fromChk, int ghostIdx);
507
508   ///find the ghost received from 'transChk' at index 'idxTrans' and add this ghost as received from 'fromChk'
509   void updateIdxlList(int fromChk, int idxTrans, int transChk);
510   ///remove this node from this idxl list of chunk 'fromChk'
511   void removeIDXLRemote(int fromChk, int sharedIdx, int type);
512   ///find the shared node with 'transChk' at index 'sharedIdx' and send this as a ghost to 'fromChk'
513   void addTransIDXLRemote(int fromChk, int sharedIdx, int type);
514   ///verify that the size of the idxl list is same on this chunk and 'fromChk'
515   void verifyIdxlList(int fromChk, int size, int type);
516
517   ///lock the idxl list for 'fromChk' on this chunk (blocking call)
518   void idxllockRemote(int fromChk, int type);
519   ///unlock the idxl list for 'fromChk' on this chunk
520   void idxlunlockRemote(int fromChk, int type);
521
522   ///Return the lock owner for this node if there is one (return -1 otherwise)
523   intMsg *hasLockRemoteNode(int sharedIdx, int fromChk, int isGhost);
524   ///Reassign lock on this node
525   void modifyLockAll(int fromChk, int sharedIdx);
526   ///verify that this lock is locked on the smallest chunk
527   boolMsg *verifyLock(int fromChk, int sharedIdx, int isGhost);
528   ///Verify that the number of chunks I get this node as a ghost is same as the number of chunnks that this node is shared on
529   void verifyghostsend(verifyghostsendMsg *vmsg);
530   ///Should this node be send as a ghost from this chunk to 'fromChk' (if no, return true)
531   boolMsg *shouldLoseGhost(int fromChk, int sharedIdx, int toChk);
532
533   ///If this node is not in the ghostSend list add it on the idxl lists on both chunks
534   void addghostsendl(int fromChk, int sharedIdx, int toChk, int transIdx);
535   ///add this node to the idxl ghost recv list of this chunk
536   void addghostsendl1(int fromChk, int transChk, int transIdx);
537   ///Add the node as a ghostRecv from 'toChk'
538   void addghostsendr(int fromChk, int sharedIdx, int toChk, int transIdx);
539   ///Add this node on the ghostSend list with 'fromChk'
540   void addghostsendr1(int fromChk, int transChk, int transIdx);
541   ///Will it lose this element as a ghost send to 'fromChk'
542   boolMsg *willItLose(int fromChk, int sharedIdx);
543
544   ///The element data is copied from the first element to the second
545   void interpolateElemCopy(int fromChk, int sharedIdx1, int sharedIdx2);
546   ///Remove this ghost element from the ghostRecv idxl list and delete the ghost node
547   void cleanupIDXL(int fromChk, int sharedIdx);
548   ///Purge this element on this chunk
549   void purgeElement(int fromChk, int sharedIdx);
550   ///Pack the data from this element/node and return it
551   entDataMsg *packEntData(int fromChk, int sharedIdx, bool isnode=false, int elemType=0);
552   ///Is this node a fixed node on this chunk
553   boolMsg *isFixedNodeRemote(int fromChk, int sharedIdx);
554
555   //debugging helper function
556   void finish1(void);
557   //debugging helper function
558   void finish(void);
559 };
560 // end mesh_modify.h
561
562 #endif