TMR: Use standard C++ headers
[charm.git] / src / libs / ck-libs / TMRC2D / tri.h
1 // Triangular Mesh Refinement Framework - 2D (TMR)
2 // Created by: Terry L. Wilmarth
3 #ifndef TRI_H
4 #define TRI_H
5
6 #include <vector>
7 #include "charm++.h"
8 #include "tcharm.h"
9 #include "charm-api.h"
10 #include "ref.h"
11 #include "node.h"
12 #include "edge.h"
13 #include "element.h"
14 #include "refine.decl.h"
15 #include "messages.h"
16 #include "mpi.h"
17
18 #define REFINE_PRECISION 0.8
19 #define COARSEN_PRECISION 0.8
20 #define QUALITY_MIN 0.5
21
22 // Debug level for TMRC2D: 1 = min, 2 = mod, 3 = max; off by default
23 //#define TDEBUG1
24 //#define TDEBUG2
25 //#define TDEBUG3
26
27 // ------------------------ Global Read-only Data ---------------------------
28 extern CProxy_chunk mesh;
29 class chunk;
30 CtvExtern(chunk *, _refineChunk);
31
32
33 /**
34  * The user inherits from this class to receive "split" calls,
35  * and to be informed when the refinement is complete.
36  */
37 class refineClient {
38 public:
39   virtual ~refineClient() {}
40
41   /**
42    * This triangle of our chunk is being split along this edge.
43    *
44    * For our purposes, edges are numbered 0 (connecting nodes 0 and 1), 
45    * 1 (connecting 1 and 2), and 2 (connecting 2 and 0).
46    * 
47    * Taking as A and B the (triangle-order) nodes of the splitting edge:
48    *
49    *     ____ A          ____ A   
50    *   /      |        /      |  
51    *  C       |  =>   C ----- D  <- new node
52    *   \      |        \      |   
53    *     ---- B          ---- B 
54    *
55    *   The original triangle should be shrunk to ADC; while a 
56    * new triangle should be inserted at DBC.
57    *
58    *   The new node D's location should equal A*(1-frac)+B*frac.
59    * For a simple splitter, frac will always be 0.5.
60    *
61    *   If nodes A and B are shared with some other processor,
62    * that processor will also receive a "split" call for the
63    * same edge.  If nodes A and B are shared by some other local
64    * triangle, that triangle will also receive a "split" call
65    * for the same edge.  
66    *
67    * Client's responsibilities:
68    *   -Add the new node D.  Since both sides of a shared edge
69    *      will receive a "split" call, you must ensure the node is
70    *      not added twice.
71    *   -Update connectivity for source triangle
72    *   -Add new triangle DBC.
73    */
74   // OBSOLETE
75   virtual void split(int triNo,int edgeOfTri,int movingNode,double frac) {};
76   // Split element triNo on edgeOfTri at frac; movingNode specifies
77   // which side new element is added to (it moves to the new location
78   // on edgeOfTri; frac indicates if this split is on the boundary and
79   // if it is the first or second half of the split operation
80  /* virtual void split(int triNo, int edgeOfTri, int movingNode, double frac, 
81                      int flag, int newNodeID, int newElemID, int origEdgeB, 
82                      int newEdge1B, int newEdge2B) {};*/
83
84 virtual void split(int tri, int A, int B, int C,  
85              int D, int _new, double frac,int flag, int origEdgeB, int newEdge1B, 
86              int newEdge2B){};
87
88                                  
89   // Collapse the edge between of elemId1 between endpoints nodeToKeep
90   // and nodeToDelete.  nodeToKeep's coordinates are updated to newX
91   // and newY, while nodeToDelete is removed and all references to it
92   // are replaced by references to nodeToKeep
93   virtual void collapse(int elemId, int nodeToKeep, int nodeToDelete, double newX, double newY, int flag, int updatedEdgeBoundary, double frac) {};
94   // update nodeID with new coordinates newX and newY; set new node's boundary
95   // flag to boundaryFlag
96   virtual void nodeUpdate(int nodeID, double newX, double newY, int boundaryFlag, int shareCount, int *adjChunks, int *adjIndices){};
97   // replace oldNodeID with newNodeID on element elementID and delete oldNodeID
98   virtual void nodeReplaceDelete(int elementID, int relnodeID, int oldNodeID, int newNodeID){};
99  
100  /*
101  // delete node entry at nodeID index
102   virtual void nodeDelete(int nodeID){};
103         */
104 };
105
106 class refineResults; //Used by refinement API to store intermediate results
107 class coarsenResults; 
108
109 typedef struct prioLockStruct {
110   int holderIdx;
111   int holderCid;
112   double prio;
113   prioLockStruct *next;
114 } *prioLockRequests;
115
116 // ---------------------------- Chare Arrays -------------------------------
117 class chunk : public TCharmClient1D {
118   // current sizes of arrays allocated for the mesh
119   int sizeElements, sizeEdges, sizeNodes;
120   // first empty slot in each mesh array
121   int firstFreeElement, firstFreeEdge, firstFreeNode;
122
123   int edgesSent, edgesRecvd, first;
124   // These are for element sorting
125  typedef struct {
126     int elID;
127     double len;
128   } elemHeap; //CHANGED
129   elemHeap *coarsenElements;
130   elemHeap *refineElements;
131   elemHeap *refineStack; //CHANGED
132   int refineTop, refineHeapSize, coarsenHeapSize; //CHANGED
133
134   void setupThreadPrivate(CthThread forThread) {
135     CtvAccessOther(forThread, _refineChunk) = this;
136   }
137   // information about connectivity and location of ghost elements
138   int *conn, *gid, additions;
139   
140   // debug_counter is used to print successive snapshots of the chunk
141   // and match them up to other chunk snapshots; refineInProgress
142   // flags that the refinement loop is active
143   int debug_counter, refineInProgress, coarsenInProgress;
144
145   // meshLock is used to lock the mesh for expansion; if meshlock is
146   // zero, the mesh can be either accessed or locked; accesses to the
147   // mesh (by a chunk method) decrement the lock, and when the
148   // accesses are complete, the lock is incremented; when an expansion
149   // of the mesh is required, the meshExpandFlag is set, indicating
150   // that no more accesses will be allowed to the mesh until the
151   // adjuster gets control and completes the expansion; when the
152   // adjuster gets control, it sets meshLock to 1 and when it is
153   // finished, it resets both variables to zero.  See methods below.
154   int meshLock, meshExpandFlag;
155
156   // private helper methods used by FEM interface functions
157   void deriveNodes();
158   int edgeLocal(elemRef e1, elemRef e2);
159   int getNbrRefOnEdge(int n1, int n2, int *conn, int nGhost, int *gid, 
160                       int idx, elemRef *er);
161   int hasEdge(int n1, int n2, int *conn, int idx);
162   
163  public:
164   // Data fields for this chunk's array index, and counts of elements,
165   // edges, and nodes located on this chunk; numGhosts is numElements
166   // plus number of ghost elements surrounding this chunk
167   int cid, numElements, numEdges, numNodes, numGhosts, numChunks;
168   //meshID passed in from FEM framework.
169   int meshID;
170   FEM_Mesh *meshPtr;
171
172   refineResults *refineResultsStorage;
173   coarsenResults *coarsenResultsStorage;
174
175   // the chunk's components, left public for sanity's sake
176   std::vector<element> theElements;
177   std::vector<edge> theEdges;
178   std::vector<node> theNodes;
179
180   // client to report refinement split information to
181   refineClient *theClient;
182
183   // range of occupied slots in each mesh array
184   int elementSlots, edgeSlots, nodeSlots;
185
186   int lock, lockHolderIdx, lockHolderCid, lockCount;
187   double lockPrio;
188   prioLockRequests lockList;
189
190   // Basic constructors
191   chunk(chunkMsg *);
192   chunk(CkMigrateMessage *m) : TCharmClient1D(m) { };
193   
194   void sanityCheck(void);
195   void validCheck(void);
196  
197   // entry methods
198   void deriveBoundaries(int *conn, int *gid);
199   void tweakMesh();
200   void improveChunk();
201   void improve();
202   
203   // deriveEdges creates nodes from the element & ghost info, then creates
204   // unique edges for each adjacent pair of nodes
205   void deriveEdges(int *conn, int *gid, const int *edgeBounds, const int *edgeConn,
206                    int nEdges);
207
208   // This initiates a refinement for a single element
209   void refineElement(int idx, double area);
210   // This loops through all elements performing refinements as needed
211   void refiningElements();
212
213   // This initiates a coarsening for a single element
214   void coarsenElement(int idx, double area);
215   // This loops through all elements performing coarsenings as needed
216   void coarseningElements();
217
218   // The following methods simply provide remote access to local data
219   // See above for details of each
220   intMsg *safeToMoveNode(int idx, double x, double y);
221   splitOutMsg *split(int idx, elemRef e, int oIdx, int fIdx);
222   void collapse(int idx, elemRef e, int kIdx, int dIdx, elemRef kNbr, 
223                 elemRef dNbr, edgeRef kEdge, edgeRef dEdge, node newN,
224                 double frac);
225   splitOutMsg *flipPreventE(int idx, elemRef e, int kIdx, int dIdx,
226                             elemRef kNbr, elemRef dNbr, edgeRef kEdge, 
227                             edgeRef dEdge, node newN);
228   void nodeReplaceDelete(int kIdx, int dIdx, node nn, int shared, int *chk, 
229                          int *idx);
230   boolMsg *flipPrevent(int kIdx, int dIdx, node nn, int shared, int *chk, 
231                          int *idx);
232   intMsg *isPending(int idx, objRef e);
233   void checkPending(int idx, objRef aRef);
234   void checkPending(int idx, objRef aRef1, objRef aRef2);
235   void updateElement(int idx, objRef oldval, objRef newval, int b);
236   void updateElementEdge(int idx, objRef oldval, objRef newval);
237   void updateReferences(int idx, objRef oldval, objRef newval);
238   doubleMsg *getArea(int n);
239   void resetEdge(int n);
240   refMsg *getNbr(int idx, objRef aRef);
241   void setTargetArea(int idx, double aDouble);
242   void resetTargetArea(int idx, double aDouble);
243   void reportPos(int idx, double x, double y);
244
245   // meshLock methods
246   void accessLock();  // waits until meshExpandFlag not set, then decs meshLock
247   void releaseLock(); // incs meshLock
248   void adjustFlag();  // sets meshExpandFlag
249   void adjustLock();  // waits until meshLock is 0, then sets it to 1
250   void adjustRelease();  // resets meshLock and meshExpandFlag to 0
251
252   // used to print snapshots of all chunks at once (more or less)
253   void print();
254
255   // *** These methods are part of the interface with the FEM framework ***
256   // create a chunk's mesh data
257   void newMesh(int meshID_,int nEl, int nGhost,const int *conn_,const 
258                int *gid_, int nnodes, const int *boundaries, int nEdges,
259                const int *edgeConn, const int *edgeBounds, int idxOffset);
260   // Sets target areas specified by desiredArea, starts refining
261   void multipleRefine(double *desiredArea, refineClient *client);
262   // Sets target areas specified by desiredArea, starts coarsening
263   void multipleCoarsen(double *desiredArea, refineClient *client);
264   // updateNodeCoords sets node coordinates, recalculates element areas
265   void updateNodeCoords(int nNode, double *coord, int nEl);
266
267
268   // add an edge on a remote chunk
269   void addRemoteEdge(int elem, int localEdge, edgeRef er);
270
271   // local methods
272   // These access and set local flags
273   void setRefining() { refineInProgress = 1; }
274   int isRefining() { return refineInProgress; }
275
276   // these methods allow for run-time additions/modifications to the chunk
277   void allocMesh(int nEl);
278   void adjustMesh();
279   intMsg *addNode(node n, int b1, int b2, int internal);
280   //int addNode(node n);
281   edgeRef addEdge(int n1, int n2, int b);
282   edgeRef addEdge(int n1, int n2, const int *edgeBounds,const int *edgeConn, int nEdges); 
283   elemRef addElement(int n1, int n2, int n3);
284   elemRef addElement(int n1, int n2, int n3,
285                       edgeRef er1, edgeRef er2, edgeRef er3);
286   void removeNode(int n);
287   void removeEdge(int n);
288   void removeElement(int n);
289   // prints a snapshot of the chunk to file
290   void debug_print(int c);
291   void out_print();
292   void dump();
293
294   intMsg *lockChunk(int lhc, int lhi, double prio);
295   void unlockChunk(int lhc, int lhi);
296   int lockLocalChunk(int lhc, int lhi, double prio);
297   void unlockLocalChunk(int lhc, int lhi);
298   void removeLock(int lhc, int lhi);
299   void insertLock(int lhc, int lhi, double prio);
300   void fixNode(int nIdx, int chkid);
301   int joinCommLists(int nIdx, int shd, int *chk, int *idx, int *rChk, 
302                     int *rIdx);
303   void addToStack(int eIdx, double len, int cFlag);
304   void rebubble(int cFlag);
305   void Insert(int elID, double len, int cFlag);
306   int Delete_Min(int cFlag);
307
308   intMsg *getBoundary(int edgeIdx);
309
310   void incnonCoarsen(int idx);
311   void resetnonCoarsen(int idx);
312   intMsg *neighboring(int idx, elemRef e);
313   intMsg *safeToCoarsen(int idx, edgeRef e);
314 };
315
316 #endif