00001
00002
00003
00004
00005
00006 #include <stdlib.h>
00007 #include <unistd.h>
00008 #include <stdio.h>
00009 #include <math.h>
00010 #include "charm++.h"
00011 #include "charm-api.h"
00012 #include "tcharm.h"
00013 #include "mpi.h"
00014 #include "tri.h"
00015 #include "refine.h"
00016
00017
00018 CLINKAGE void REFINE2D_Init(void) {
00019 TCHARM_API_TRACE("REFINE2D_Init", "refine");
00020 TCharm *tc=TCharm::get();
00021
00022
00023 MPI_Comm comm=MPI_COMM_WORLD;
00024 int rank; MPI_Comm_rank(comm,&rank);
00025 CkArrayID refArrayID;
00026 if (rank==0)
00027 {
00028 CkArrayOptions opts;
00029 opts.bindTo(tc->getProxy());
00030 refArrayID=CProxy_chunk::ckNew(new chunkMsg, opts);
00031 }
00032 MPI_Bcast(&refArrayID,sizeof(refArrayID),MPI_BYTE, 0,comm);
00033 mesh=refArrayID;
00034
00035
00036 chunkMsg *cm = new chunkMsg;
00037 cm->nChunks = tc->getNumElements();
00038 cm->myThreads = tc->getProxy();
00039 mesh[rank].insert(cm);
00040 tc->suspend();
00041 }
00042 FLINKAGE void FTN_NAME(REFINE2D_INIT,refine2d_init)(void)
00043 {
00044 REFINE2D_Init();
00045 }
00046
00047
00048 CLINKAGE void REFINE2D_NewMesh(int nEl,int nGhost,const int *conn,const int *gid)
00049 {
00050 TCHARM_API_TRACE("REFINE2D_NewMesh", "refine");
00051 if (!CtvAccess(_refineChunk))
00052 CkAbort("Forgot to call REFINE_Attach!!\n");
00053
00054
00055 MPI_Barrier(MPI_COMM_WORLD);
00056 CtvAccess(_refineChunk)->newMesh(nEl,nGhost,conn, gid, 0);
00057 CkWaitQD();
00058 }
00059 FLINKAGE void FTN_NAME(REFINE2D_NEWMESH,refine2d_newmesh)
00060 (int *nEl,int *nGhost,const int *conn,const int *gid)
00061 {
00062 TCHARM_API_TRACE("REFINE2D_NewMesh", "refine");
00063 if (!CtvAccess(_refineChunk))
00064 CkAbort("Forgot to call REFINE_Attach!!\n");
00065
00066 CtvAccess(_refineChunk)->newMesh(*nEl, *nGhost,conn, gid, 1);
00067 CkWaitQD();
00068 }
00069
00070
00071 class refineResults {
00072 int nResults;
00073 class resRec {
00074 public:
00075 int t,s,n;
00076 double f;
00077 int flag;
00078 resRec(int t_,int s_,int n_,double f_)
00079 :t(t_), s(s_), n(n_), f(f_) {flag =0;}
00080 resRec(int t_,int s_,int n_,double f_,int flag_)
00081 :t(t_), s(s_), n(n_), f(f_),flag(flag_) {}
00082 };
00083 std::vector<resRec> res;
00084
00085
00086 int otherThan(int a,int b) {
00087 if (a==b) CkAbort("Opposite node is moving!");
00088 for (int i=0;i<3;i++)
00089 if (i!=a && i!=b) return i;
00090 CkAbort("Logic error in refine.C::otherThan");
00091 return -1;
00092 }
00093 public:
00094 refineResults(void) {nResults=0;}
00095 void add(int tri_,int side_,int n_,double frac_) {
00096 nResults++;
00097 res.push_back(resRec(tri_,side_,n_,frac_));
00098 }
00099 void add(int tri_,int side_,int n_,double frac_,int flag) {
00100 nResults++;
00101 res.push_back(resRec(tri_,side_,n_,frac_,flag));
00102 }
00103
00104 int countResults(void) const {return nResults;}
00105 void extract(int i,const int *conn,int *triDest,int *A,int *B,int *C,double *fracDest,int idxBase,int *flags) {
00106 if ((i<0) || (i>=(int)res.size()))
00107 CkAbort("Invalid index in REFINE2D_Get_Splits");
00108
00109 int tri=res[i].t;
00110 *triDest=tri+idxBase;
00111 int edgeOfTri=res[i].s;
00112 int movingNode=res[i].n;
00113
00114 int c=(edgeOfTri+2)%3;
00115 *A=conn[3*tri+movingNode];
00116 *B=conn[3*tri+otherThan(c,movingNode)];
00117 *C=conn[3*tri+c];
00118 *fracDest=res[i].f;
00119 *flags = res[i].flag;
00120 if (i==(int)res.size()-1) {
00121 delete this;
00122 chunk *C = CtvAccess(_refineChunk);
00123 C->refineResultsStorage=NULL;
00124 }
00125 }
00126 };
00127
00128 class resultsRefineClient : public refineClient {
00129 refineResults *res;
00130 public:
00131 resultsRefineClient(refineResults *res_) :res(res_) {}
00132 void split(int tri, int side, int node, double frac) {
00133 #if 0
00134
00135 if (side==1) side=2;
00136 else if (side==2) side=1;
00137 #endif
00138 res->add(tri, side, node, frac);
00139 }
00140 void split(int tri, int side, int node, double frac,int flag) {
00141 res->add(tri, side, node, frac,flag);
00142 }
00143
00144 };
00145
00146
00147 CLINKAGE void REFINE2D_Split(int nNode,double *coord,int nEl,double *desiredArea)
00148 {
00149 TCHARM_API_TRACE("REFINE2D_Split", "refine");
00150 chunk *C = CtvAccess(_refineChunk);
00151 if (!C)
00152 CkAbort("REFINE2D_Split failed> Did you forget to call REFINE2D_Attach?");
00153 C->refineResultsStorage=new refineResults;
00154 resultsRefineClient client(C->refineResultsStorage);
00155
00156 C->updateNodeCoords(nNode, coord, nEl);
00157 C->multipleRefine(desiredArea, &client);
00158 CkWaitQD();
00159 }
00160 FLINKAGE void FTN_NAME(REFINE2D_SPLIT,refine2d_split)
00161 (int *nNode,double *coord,int *nEl,double *desiredArea)
00162 {
00163 REFINE2D_Split(*nNode,coord,*nEl,desiredArea);
00164 }
00165
00166 static refineResults *getResults(void) {
00167 chunk *C = CtvAccess(_refineChunk);
00168 if (!C)
00169 CkAbort("Did you forget to call REFINE2D_Init?");
00170 refineResults *ret=C->refineResultsStorage;
00171 if (ret==NULL)
00172 CkAbort("Did you forget to call REFINE2D_Begin?");
00173 return ret;
00174 }
00175
00176 CLINKAGE int REFINE2D_Get_Split_Length(void)
00177 {
00178 TCHARM_API_TRACE("REFINE2D_Get_Split_Length", "refine");
00179 return getResults()->countResults();
00180 }
00181 FLINKAGE int FTN_NAME(REFINE2D_GET_SPLIT_LENGTH,refine2d_get_split_length)(void)
00182 {
00183 return REFINE2D_Get_Split_Length();
00184 }
00185
00186 CLINKAGE void REFINE2D_Get_Split
00187 (int splitNo,const int *conn,int *triDest,int *A,int *B,int *C,double *fracDest,int *flags)
00188 {
00189 TCHARM_API_TRACE("REFINE2D_Get_Split", "refine");
00190 refineResults *r=getResults();
00191 r->extract(splitNo,conn,triDest,A,B,C,fracDest,0,flags);
00192 }
00193 FLINKAGE void FTN_NAME(REFINE2D_GET_SPLIT,refine2d_get_split)
00194 (int *splitNo,const int *conn,int *triDest,int *A,int *B,int *C,double *fracDest, int *flags)
00195 {
00196 TCHARM_API_TRACE("REFINE2D_Get_Split", "refine");
00197 refineResults *r=getResults();
00198 r->extract(*splitNo-1,conn,triDest,A,B,C,fracDest,1,flags);
00199 }
00200
00201
00202 static int checkElement(chunk *C,const element &e,const int *uc,int idxBase)
00203 {
00204 int nMismatch=0;
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 return nMismatch;
00217 }
00218
00219 static void checkConn(int nEl,const int *conn,int idxBase,int nNode)
00220 {
00221 chunk *C = CtvAccess(_refineChunk);
00222 if (!C) CkAbort("Did you forget to call REFINE2D_Attach?");
00223 C->sanityCheck();
00224
00225 if (nEl != C->numElements || nNode != C->numNodes) {
00226 CkPrintf("ERROR: inconsistency in REFINE2D_Check on chunk %d:\n"
00227 " your nEl (%d); my numElements (%d)\n"
00228 " your nNode (%d); my numNodes (%d)\n",
00229 C->cid, nEl, C->numElements, nNode,C->numNodes);
00230 CkAbort("User code/library numbering inconsistency in REFINE2D");
00231 }
00232 int i;
00233 int nErrs=0;
00234 for (i=0;i<nEl;i++)
00235 {
00236 const element &e=C->theElements[i];
00237 const int *uc=&conn[3*i];
00238 int elErrs=checkElement(C,e,uc,idxBase);
00239 nErrs+=elErrs;
00240 if (elErrs!=0)
00241 {
00242
00243
00244
00245
00246
00247
00248
00249 }
00250 }
00251 if (nErrs!=0) {
00252 CkAbort("REFINE2D_Check> Major errors found. Exiting.");
00253 }
00254 }
00255
00256 CLINKAGE void REFINE2D_Check(int nEl,const int *conn,int nNodes) {
00257 checkConn(nEl,conn,0,nNodes);
00258 }
00259 FLINKAGE void FTN_NAME(REFINE2D_CHECK,refine2d_check)
00260 (int *nEl,const int *conn,int *nNodes)
00261 {
00262 checkConn(*nEl,conn,1,*nNodes);
00263 }
00264
00265
00266