00001
00002
00003
00004 #include <stdlib.h>
00005 #include <unistd.h>
00006 #include <stdio.h>
00007 #include <math.h>
00008 #include "charm++.h"
00009 #include "charm-api.h"
00010 #include "tcharm.h"
00011 #include "mpi.h"
00012 #include "tri.h"
00013 #include "refine.h"
00014
00015
00016 CLINKAGE void REFINE2D_Init(void) {
00017 TCHARM_API_TRACE("REFINE2D_Init", "refine");
00018 TCharm *tc=TCharm::get();
00019
00020
00021 MPI_Comm comm=MPI_COMM_WORLD;
00022 int rank; MPI_Comm_rank(comm,&rank);
00023 CkArrayID refArrayID;
00024 if (rank==0)
00025 {
00026 CkArrayOptions opts;
00027 opts.bindTo(tc->getProxy());
00028 refArrayID=CProxy_chunk::ckNew(new chunkMsg, opts);
00029 }
00030 MPI_Bcast(&refArrayID,sizeof(refArrayID),MPI_BYTE, 0,comm);
00031 mesh=refArrayID;
00032
00033
00034 chunkMsg *cm = new chunkMsg;
00035 cm->nChunks = tc->getNumElements();
00036 cm->myThreads = tc->getProxy();
00037 mesh[rank].insert(cm);
00038 tc->suspend();
00039 }
00040 FLINKAGE void FTN_NAME(REFINE2D_INIT,refine2d_init)(void)
00041 {
00042 REFINE2D_Init();
00043 }
00044
00045
00046 CLINKAGE void REFINE2D_NewMesh(int meshID,int nEl,int nGhost,int nnodes,const int *conn,const int *gid,const int *boundaries, const int *edgeBounds, const int *edgeConn, int nEdges)
00047 {
00048 TCHARM_API_TRACE("REFINE2D_NewMesh", "refine");
00049 if (!CtvAccess(_refineChunk))
00050 CkAbort("Forgot to call REFINE_Attach!!\n");
00051
00052 CtvAccess(_refineChunk)->newMesh(meshID, nEl, nGhost, conn, gid, nnodes,
00053 boundaries, nEdges, edgeConn, edgeBounds, 0);
00054 MPI_Barrier(MPI_COMM_WORLD);
00055 CkWaitQD();
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 class refineResults {
00073 std::vector<refineData> res;
00074 int nResults;
00075
00076
00077 int otherThan(int a,int b) {
00078 if (a==b) CkAbort("Opposite node is moving!");
00079 for (int i=0;i<3;i++)
00080 if (i!=a && i!=b) return i;
00081 CkAbort("Logic error in refine.C::otherThan");
00082 return -1;
00083 }
00084 public:
00085 refineResults(void) {nResults=0;}
00086 refineData createRefineData(int tri, int A, int B, int C,
00087 int D, int _new, double frac,int flag, int origEdgeB, int newEdge1B,
00088 int newEdge2B){
00089 refineData d;
00090 d.tri = tri;
00091 d.A = A;
00092 d.B = B;
00093 d.C = C;
00094 d.D = D;
00095 d._new = _new;
00096 d.frac = frac;
00097 d.flag = flag;
00098 d.origEdgeB = origEdgeB;
00099 d.newEdge1B = newEdge1B;
00100 d.newEdge2B = newEdge2B;
00101 return d;
00102 }
00103 void add(refineData &d){
00104 nResults++;
00105 res.push_back(d);
00106 };
00107
00108 int countResults(void) const {return nResults;}
00109
00110 void extract(int i, refineData *d) {
00111 *d = res[i];
00112 }
00113 };
00114 void FEM_Modify_IDXL(FEM_Refine_Operation_Data *data,refineData &d);
00115
00116 class resultsRefineClient : public refineClient {
00117 refineResults *res;
00118 FEM_Refine_Operation_Data *data;
00119 public:
00120 resultsRefineClient(refineResults *res_,FEM_Refine_Operation_Data *data_) :res(res_),data(data_) {}
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 void split(int tri, int A, int B, int C,
00131 int D, int _new, double frac,int flag, int origEdgeB, int newEdge1B,
00132 int newEdge2B) {
00133 refineData d = res->createRefineData(tri,A,B,C,D, _new,frac,flag,origEdgeB,
00134 newEdge1B,newEdge2B);
00135
00136 FEM_Modify_IDXL(data,d);
00137
00138 res->add(d);
00139 }
00140 };
00141
00142 class coarsenResults {
00143
00144 std::vector<coarsenData> res;
00145 public:
00146 coarsenResults(){}
00147 coarsenData addCollapse(int elementID, int nodeToKeep, int nodeToDelete,
00148 double nX, double nY, int flag, int boundFlag,
00149 double frac)
00150 {
00151 coarsenData d;
00152 d.type = COLLAPSE;
00153 d.data.cdata.elemID = elementID;
00154 d.data.cdata.nodeToKeep = nodeToKeep;
00155 d.data.cdata.nodeToDelete = nodeToDelete;
00156 d.data.cdata.newX = nX;
00157 d.data.cdata.newY = nY;
00158 d.data.cdata.flag = flag;
00159 d.data.cdata.boundaryFlag = boundFlag;
00160 d.data.cdata.frac = frac;
00161 return d;
00162 };
00163 coarsenData addUpdate(int nodeID, double newX, double newY, int boundaryFlag)
00164 {
00165 coarsenData d;
00166 d.type = UPDATE;
00167 d.data.udata.nodeID = nodeID;
00168 d.data.udata.newX = newX;
00169 d.data.udata.newY = newY;
00170 d.data.udata.boundaryFlag = boundaryFlag;
00171
00172 return d;
00173 };
00174 coarsenData addReplaceDelete(int elemID, int relnodeID, int oldNodeID,
00175 int newNodeID)
00176 {
00177 coarsenData d;
00178 d.type = REPLACE;
00179 d.data.rddata.elemID = elemID;
00180 d.data.rddata.relnodeID = relnodeID;
00181 d.data.rddata.oldNodeID = oldNodeID;
00182 d.data.rddata.newNodeID = newNodeID;
00183
00184 return d;
00185 };
00186 int countResults(){return res.size();}
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 void extract(int i, coarsenData *output){
00204 *output = res[i];
00205 }
00206 };
00207
00208
00209
00210
00211 class FEM_Operation_Data;
00212 void FEM_Coarsen_Operation(FEM_Operation_Data *coarsen_data,
00213 coarsenData &operation);
00214
00215 class resultsCoarsenClient : public refineClient {
00216 coarsenResults *res;
00217 FEM_Operation_Data *data;
00218 public:
00219 resultsCoarsenClient(coarsenResults *res_, FEM_Operation_Data *data_=NULL)
00220 : res(res_),data(data_){};
00221 void collapse(int elementID, int nodeToKeep, int nodeToDelete, double nX,
00222 double nY, int flag, int b, double frac)
00223 {
00224 coarsenData d = res->addCollapse(elementID, nodeToKeep, nodeToDelete, nX,
00225 nY, flag, b, frac);
00226 FEM_Coarsen_Operation(data,d);
00227 }
00228 void nodeUpdate(int nodeID, double newX, double newY, int boundaryFlag)
00229 {
00230 coarsenData d = res->addUpdate(nodeID,newX,newY,boundaryFlag);
00231 FEM_Coarsen_Operation(data,d);
00232 }
00233 void nodeReplaceDelete(int elementID, int relnodeID, int oldNodeID,
00234 int newNodeID)
00235 {
00236 coarsenData d = res->addReplaceDelete(elementID, relnodeID, oldNodeID,
00237 newNodeID);
00238 FEM_Coarsen_Operation(data,d);
00239 }
00240 };
00241
00242
00243
00244 CLINKAGE void REFINE2D_Split(int nNode,double *coord,int nEl,double *desiredArea,FEM_Refine_Operation_Data *refine_data)
00245 {
00246 TCHARM_API_TRACE("REFINE2D_Split", "refine");
00247 chunk *C = CtvAccess(_refineChunk);
00248 if (!C)
00249 CkAbort("REFINE2D_Split failed> Did you forget to call REFINE2D_Attach?");
00250 C->refineResultsStorage=new refineResults;
00251 resultsRefineClient client(C->refineResultsStorage,refine_data);
00252
00253 C->updateNodeCoords(nNode, coord, nEl);
00254 C->multipleRefine(desiredArea, &client);
00255 }
00256
00257 CLINKAGE void REFINE2D_Coarsen(int nNode, double *coord, int nEl,
00258 double *desiredArea, FEM_Operation_Data *data)
00259 {
00260 TCHARM_API_TRACE("REFINE2D_Coarsen", "coarsen");
00261 chunk *C = CtvAccess(_refineChunk);
00262 if (!C)
00263 CkAbort("REFINE2D_Split failed> Did you forget to call REFINE2D_Attach?");
00264 C->coarsenResultsStorage=new coarsenResults;
00265 resultsCoarsenClient client(C->coarsenResultsStorage,data);
00266
00267 C->updateNodeCoords(nNode, coord, nEl);
00268 C->multipleCoarsen(desiredArea, &client);
00269 }
00270
00271
00272 FLINKAGE void FTN_NAME(REFINE2D_SPLIT,refine2d_split)
00273 (int *nNode,double *coord,int *nEl,double *desiredArea,FEM_Refine_Operation_Data *data)
00274 {
00275 REFINE2D_Split(*nNode,coord,*nEl,desiredArea,data);
00276 }
00277
00278 static refineResults *getResults(void) {
00279 chunk *C = CtvAccess(_refineChunk);
00280 if (!C)
00281 CkAbort("Did you forget to call REFINE2D_Init?");
00282 refineResults *ret=C->refineResultsStorage;
00283 if (ret==NULL)
00284 CkAbort("Did you forget to call REFINE2D_Begin?");
00285 return ret;
00286 }
00287
00288 CLINKAGE int REFINE2D_Get_Split_Length(void)
00289 {
00290 TCHARM_API_TRACE("REFINE2D_Get_Split_Length", "refine");
00291 return getResults()->countResults();
00292 }
00293 FLINKAGE int FTN_NAME(REFINE2D_GET_SPLIT_LENGTH,refine2d_get_split_length)(void)
00294 {
00295 return REFINE2D_Get_Split_Length();
00296 }
00297
00298 CLINKAGE void REFINE2D_Get_Split
00299 (int splitNo,refineData *d)
00300 {
00301 TCHARM_API_TRACE("REFINE2D_Get_Split", "refine");
00302 refineResults *r=getResults();
00303 r->extract(splitNo,d);
00304 }
00305 FLINKAGE void FTN_NAME(REFINE2D_GET_SPLIT,refine2d_get_split)
00306 (int *splitNo,refineData *d)
00307 {
00308 TCHARM_API_TRACE("REFINE2D_Get_Split", "refine");
00309 refineResults *r=getResults();
00310 r->extract(*splitNo-1,d);
00311 }
00312
00313 static coarsenResults *getCoarsenResults(void) {
00314 chunk *C = CtvAccess(_refineChunk);
00315 if (!C)
00316 CkAbort("Did you forget to call REFINE2D_Init?");
00317 coarsenResults *ret=C->coarsenResultsStorage;
00318 if (ret==NULL)
00319 CkAbort("Did you forget to call REFINE2D_Coarsen?");
00320 return ret;
00321 }
00322
00323
00324 CLINKAGE int REFINE2D_Get_Collapse_Length(){
00325 return getCoarsenResults()->countResults();
00326 }
00327
00328
00329
00330
00331
00332 CLINKAGE void REFINE2D_Get_Collapse(int i,coarsenData *output){
00333 getCoarsenResults()->extract(i,output);
00334 }
00335
00336
00337 static int checkElement(chunk *C,const element &e,const int *uc,int idxBase)
00338 {
00339 int nMismatch=0;
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 return nMismatch;
00352 }
00353
00354 static void checkConn(int nEl,const int *conn,int idxBase,int nNode)
00355 {
00356 chunk *C = CtvAccess(_refineChunk);
00357 if (!C) CkAbort("Did you forget to call REFINE2D_Attach?");
00358
00359 if (nEl != C->numElements || nNode != C->numNodes) {
00360 CkPrintf("ERROR: inconsistency in REFINE2D_Check on chunk %d:\n"
00361 " your nEl (%d); my numElements (%d)\n"
00362 " your nNode (%d); my numNodes (%d)\n",
00363 C->cid, nEl, C->numElements, nNode,C->numNodes);
00364 CkAbort("User code/library numbering inconsistency in REFINE2D");
00365 }
00366 int i;
00367 int nErrs=0;
00368 for (i=0;i<nEl;i++) {
00369 const element &e=C->theElements[i];
00370 const int *uc=&conn[3*i];
00371 int elErrs=checkElement(C,e,uc,idxBase);
00372 nErrs+=elErrs;
00373 if (elErrs!=0) {
00374
00375
00376
00377
00378
00379
00380
00381 }
00382 }
00383 if (nErrs!=0) {
00384 CkAbort("REFINE2D_Check> Major errors found. Exiting.");
00385 }
00386 }
00387
00388 CLINKAGE void REFINE2D_Check(int nEl,const int *conn,int nNodes) {
00389 checkConn(nEl,conn,0,nNodes);
00390 }
00391 FLINKAGE void FTN_NAME(REFINE2D_CHECK,refine2d_check)
00392 (int *nEl,const int *conn,int *nNodes)
00393 {
00394 checkConn(*nEl,conn,1,*nNodes);
00395 }
00396
00397
00398