00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "fem.h"
00012 #include "fem_impl.h"
00013 #include "charm-api.h"
00014
00015 #define S FEM_Mesh_default_write()
00016 #define G FEM_Mesh_default_read()
00017
00018
00019
00020
00021
00022 static void renumberGhostConn(int nodeGhosts,
00023 int *conn,int per,int n,int idxbase)
00024 {
00025 for (int r=0;r<n;r++)
00026 for (int c=0;c<per;c++)
00027 {
00028 int i=conn[r*per+c];
00029 if (idxbase==0) {
00030 if (FEM_Is_ghost_index(i))
00031 conn[r*per+c]=nodeGhosts+FEM_From_ghost_index(i);
00032 } else {
00033 if (i<0)
00034 conn[r*per+c]=nodeGhosts+(-i);
00035 }
00036 }
00037 }
00038
00039
00040 static void mesh_conn(int fem_mesh,int entity,int *conn,int idxBase) {
00041 int n=FEM_Mesh_get_length(fem_mesh,entity);
00042 int per=FEM_Mesh_get_width(fem_mesh,entity,FEM_CONN);
00043 FEM_Mesh_data(fem_mesh,entity,FEM_CONN, conn, 0,n, FEM_INDEX_0+idxBase,per);
00044
00045 if (FEM_Mesh_is_get(fem_mesh))
00046 {
00047 int nGhosts=FEM_Mesh_get_length(fem_mesh,FEM_GHOST+entity);
00048 if (nGhosts>0) {
00049 int *ghostConn=&conn[n*per];
00050 FEM_Mesh_data(fem_mesh,FEM_GHOST+entity,FEM_CONN,
00051 ghostConn, 0,nGhosts, FEM_INDEX_0+idxBase,per);
00052 renumberGhostConn(FEM_Mesh_get_length(fem_mesh,FEM_NODE),ghostConn,per,nGhosts,idxBase);
00053 }
00054 }
00055 }
00056
00057
00058 static void mesh_data(int fem_mesh,int entity, int dtype,void *v_data) {
00059 int n=FEM_Mesh_get_length(fem_mesh,entity);
00060 int per=FEM_Mesh_get_width(fem_mesh,entity,FEM_DATA);
00061 FEM_Mesh_data(fem_mesh,entity,FEM_DATA,v_data, 0,n, dtype,per);
00062
00063 if (FEM_Mesh_is_get(fem_mesh))
00064 {
00065 int nGhosts=FEM_Mesh_get_length(fem_mesh,FEM_GHOST+entity);
00066 char *data=(char *)v_data;
00067 int size=IDXL_Layout::type_size(dtype);
00068 if (nGhosts>0)
00069 FEM_Mesh_data(fem_mesh,FEM_GHOST+entity,FEM_DATA,
00070 (void *)&data[n*per*size], 0,nGhosts, dtype,per);
00071 }
00072 }
00073
00074
00075
00076
00077 CLINKAGE void FEM_Set_node(int nNodes,int doublePerNode) {
00078 FEM_Mesh_set_length(S,FEM_NODE,nNodes);
00079 FEM_Mesh_set_width(S,FEM_NODE,FEM_DATA,doublePerNode);
00080 }
00081 FORTRAN_AS_C(FEM_SET_NODE,FEM_Set_node,fem_set_node,
00082 (int *n,int *d), (*n,*d)
00083 )
00084
00085 CLINKAGE void FEM_Set_elem(int elType,int n,int doublePerElem,int nodePerElem) {
00086 FEM_Mesh_set_length(S,FEM_ELEM+elType,n);
00087 FEM_Mesh_set_width(S,FEM_ELEM+elType,FEM_DATA,doublePerElem);
00088 FEM_Mesh_set_width(S,FEM_ELEM+elType,FEM_CONN,nodePerElem);
00089 }
00090 FORTRAN_AS_C(FEM_SET_ELEM,FEM_Set_elem,fem_set_elem,
00091 (int *t,int *n,int *d,int *c), (*t,*n,*d,*c)
00092 )
00093
00094
00095
00096
00097 CLINKAGE void FEM_Set_node_data(const double *data) {
00098 mesh_data(S,FEM_NODE,FEM_DOUBLE,(void *)data);
00099 }
00100 FORTRAN_AS_C(FEM_SET_NODE_DATA_R,FEM_Set_node_data,fem_set_node_data_r,
00101 (const double *data), (data)
00102 )
00103
00104 CLINKAGE void FEM_Set_elem_data(int elType,const double *data) {
00105 mesh_data(S,FEM_ELEM+elType,FEM_DOUBLE,(void *)data);
00106 }
00107 FORTRAN_AS_C(FEM_SET_ELEM_DATA_R,FEM_Set_elem_data,fem_set_elem_data_r,
00108 (int *t,const double *d), (*t,d)
00109 )
00110
00111
00112 CLINKAGE void FEM_Set_elem_conn(int elType,const int *conn) {
00113 mesh_conn(S,FEM_ELEM+elType, (int *)conn, 0);
00114 }
00115
00116 FLINKAGE void FTN_NAME(FEM_SET_ELEM_CONN_R,fem_set_elem_conn_r)
00117 (int *elType,const int *conn)
00118 {
00119 mesh_conn(S,FEM_ELEM+*elType, (int *)conn, 1);
00120 }
00121
00122
00123 CLINKAGE void FEM_Set_sparse(int sid,int nRecords,
00124 const int *nodes,int nodesPerRec,
00125 const void *data,int dataPerRec,int dataType)
00126 {
00127 int entity=FEM_SPARSE+sid;
00128 FEM_Mesh_set_data(S,entity,FEM_CONN, (int *)nodes, 0,nRecords, FEM_INDEX_0,nodesPerRec);
00129 FEM_Mesh_set_data(S,entity,FEM_DATA, (void *)data, 0,nRecords, dataType,dataPerRec);
00130 }
00131 FLINKAGE void FTN_NAME(FEM_SET_SPARSE,fem_set_sparse)
00132 (int *sid,int *nRecords,
00133 const int *nodes,int *nodesPerRec,
00134 const void *data,int *dataPerRec,int *dataType)
00135 {
00136 int entity=FEM_SPARSE+*sid;
00137 int n=*nRecords;
00138 FEM_Mesh_set_data(S,entity,FEM_CONN, (int *)nodes, 0,n, FEM_INDEX_1,*nodesPerRec);
00139 FEM_Mesh_set_data(S,entity,FEM_DATA, (void *)data, 0,n, *dataType,*dataPerRec);
00140 }
00141
00142 CLINKAGE void FEM_Set_sparse_elem(int sid,const int *rec2elem)
00143 {
00144 int entity=FEM_SPARSE+sid;
00145 int n=FEM_Mesh_get_length(S,FEM_SPARSE+sid);
00146 FEM_Mesh_set_data(S,entity,FEM_SPARSE_ELEM, (void *)rec2elem, 0,n, FEM_INDEX_0,2);
00147 }
00148 FLINKAGE void FTN_NAME(FEM_SET_SPARSE_ELEM,fem_set_sparse_elem)
00149 (int *sid,int *rec2elem)
00150 {
00151 int entity=FEM_SPARSE+*sid;
00152 int i,n=FEM_Mesh_get_length(S,entity);
00153
00154
00155
00156
00157 for (i=0;i<n;i++) rec2elem[2*i+1]--;
00158 FEM_Mesh_set_data(S,entity,FEM_SPARSE_ELEM,
00159 (void *)rec2elem, 0,n, FEM_INDEX_0,2);
00160 for (i=0;i<n;i++) rec2elem[2*i+1]++;
00161 }
00162
00163
00164
00165
00166
00167
00168 static int mesh_get_ghost_length(int mesh,int entity) {
00169 return FEM_Mesh_get_length(mesh,entity)+FEM_Mesh_get_length(mesh,FEM_GHOST+entity);
00170 }
00171
00172
00173 CLINKAGE void FEM_Get_node(int *nNodes,int *perNode) {
00174 *nNodes=mesh_get_ghost_length(G,FEM_NODE);
00175 *perNode=FEM_Mesh_get_width(G,FEM_NODE,FEM_DATA);
00176 }
00177 FORTRAN_AS_C(FEM_GET_NODE,FEM_Get_node,fem_get_node,
00178 (int *n,int *per), (n,per))
00179
00180
00181 CLINKAGE void FEM_Get_elem(int elType,int *nElem,int *doublePerElem,int *nodePerElem) {
00182 *nElem=mesh_get_ghost_length(G,FEM_ELEM+elType);
00183 *doublePerElem=FEM_Mesh_get_width(G,FEM_ELEM+elType,FEM_DATA);
00184 *nodePerElem=FEM_Mesh_get_width(G,FEM_ELEM+elType,FEM_CONN);
00185 }
00186 FORTRAN_AS_C(FEM_GET_ELEM,FEM_Get_elem,fem_get_elem,
00187 (int *t,int *n,int *per,int *c), (*t,n,per,c))
00188
00189
00190 CLINKAGE void FEM_Get_node_data(double *data) {
00191 mesh_data(G,FEM_NODE,FEM_DOUBLE,data);
00192 }
00193 FORTRAN_AS_C(FEM_GET_NODE_DATA_R,FEM_Get_node_data,fem_get_node_data_r,
00194 (double *data), (data))
00195
00196 CLINKAGE void FEM_Get_elem_data(int elType,double *data) {
00197 mesh_data(G,FEM_ELEM+elType,FEM_DOUBLE,data);
00198 }
00199 FORTRAN_AS_C(FEM_GET_ELEM_DATA_R,FEM_Get_elem_data,fem_get_elem_data_r,
00200 (int *elType,double *data), (*elType,data))
00201
00202
00203
00204 CLINKAGE void FEM_Get_elem_conn(int elType,int *conn) {
00205 mesh_conn(G,FEM_ELEM+elType,conn,0);
00206 }
00207
00208 FLINKAGE void FTN_NAME(FEM_GET_ELEM_CONN_R, fem_get_elem_conn_r)
00209 (int *elType,int *conn)
00210 {
00211 mesh_conn(G,FEM_ELEM+*elType,conn,1);
00212 }
00213
00214
00215
00216 CLINKAGE int FEM_Get_sparse_length(int sid) {
00217 return mesh_get_ghost_length(G,FEM_SPARSE+sid);
00218 }
00219 FORTRAN_AS_C_RETURN(int, FEM_GET_SPARSE_LENGTH,FEM_Get_sparse_length,fem_get_sparse_length,
00220 (int *sid), (*sid))
00221
00222 CLINKAGE void FEM_Get_sparse(int sid,int *nodes,void *data) {
00223 int fem_mesh=G;
00224 int entity=FEM_SPARSE+sid;
00225 int dataType=FEM_Mesh_get_datatype(fem_mesh,entity,FEM_DATA);
00226 mesh_data(fem_mesh,entity,dataType,data);
00227 mesh_conn(fem_mesh,entity,nodes,0);
00228 }
00229 FLINKAGE void FTN_NAME(FEM_GET_SPARSE,fem_get_sparse)(int *sid,int *nodes,void *data) {
00230 int fem_mesh=G;
00231 int entity=FEM_SPARSE+*sid;
00232 int dataType=FEM_Mesh_get_datatype(fem_mesh,entity,FEM_DATA);
00233 mesh_data(fem_mesh,entity,dataType,data);
00234 mesh_conn(fem_mesh,entity,nodes,1);
00235 }
00236
00237 CLINKAGE int FEM_Get_node_ghost(void)
00238 {
00239 return FEM_Mesh_get_length(G,FEM_NODE);
00240 }
00241 FLINKAGE int FTN_NAME(FEM_GET_NODE_GHOST,fem_get_node_ghost)(void) {
00242 return 1+FEM_Get_node_ghost();
00243 }
00244
00245 CLINKAGE int FEM_Get_elem_ghost(int elemType)
00246 {
00247 return FEM_Mesh_get_length(G,FEM_ELEM+elemType);
00248 }
00249 FLINKAGE int FTN_NAME(FEM_GET_ELEM_GHOST,fem_get_elem_ghost)(int *elType) {
00250 return 1+FEM_Get_elem_ghost(*elType);
00251 }
00252
00253
00256 CLINKAGE void FEM_Get_sym(int elTypeOrMinusOne,int *destSym)
00257 {
00258 const char *callingRoutine="FEM_Get_sym";
00259 FEMAPI(callingRoutine);
00260 int mesh=G;
00261 int entity=FEM_ELEM+elTypeOrMinusOne;
00262 if (elTypeOrMinusOne==-1) entity=FEM_NODE;
00263 FEM_Entity &l=*FEM_Entity_lookup(mesh,entity,callingRoutine);
00264 int i,n=l.size();
00265 for (i=0;i<n;i++) destSym[i]=l.getSymmetries(i);
00266 int g=l.getGhost()->size();
00267 for (i=0;i<g;i++) destSym[n+i]=l.getGhost()->getSymmetries(i);
00268 }
00269 FLINKAGE void FTN_NAME(FEM_GET_SYM,fem_get_sym)
00270 (int *elTypeOrZero,int *destSym)
00271 {
00272 FEM_Get_sym(zeroToMinusOne(*elTypeOrZero),destSym);
00273 }
00274
00275
00276
00279 CLINKAGE void FEM_Set_mesh(int nelem, int nnodes, int nodePerElem, int* conn) {
00280 FEM_Set_node(nnodes,0);
00281 FEM_Set_elem(0,nelem,0,nodePerElem);
00282 FEM_Set_elem_conn(0,conn);
00283 }
00284 FLINKAGE void FTN_NAME(FEM_SET_MESH,fem_set_mesh)
00285 (int *nelem, int *nnodes, int *ctype, int *conn)
00286 {
00287 int elType=1,zero=0;
00288 FTN_NAME(FEM_SET_NODE,fem_set_node) (nnodes,&zero);
00289 FTN_NAME(FEM_SET_ELEM,fem_set_elem) (&elType,nelem,&zero,ctype);
00290 FTN_NAME(FEM_SET_ELEM_CONN_R,fem_set_elem_conn_r) (&elType,conn);
00291 }
00292
00293
00294
00295
00296
00297
00298 class updateState {
00299 int doWhat;
00300 MPI_Comm comm;
00301 int myRank, master;
00302 int or_mesh;
00303 int osr_mesh;
00304 int nsw_mesh;
00305 public:
00306 updateState(int doWhat_) :doWhat(doWhat_) {
00307 comm=(MPI_Comm)FEMchunk::get("FEM_Update_mesh")->defaultComm;
00308 MPI_Comm_rank(comm,&myRank);
00309 master=0;
00310 or_mesh=osr_mesh=nsw_mesh=-1;
00311 }
00312 ~updateState() {
00313 }
00314
00315 bool pre(void)
00316 {
00317
00318 or_mesh=FEM_Mesh_default_read();
00319 int ow_mesh=FEM_Mesh_default_write();
00320 FEM_Mesh_copy_globalno(or_mesh,ow_mesh);
00321 osr_mesh=FEM_Mesh_reduce(ow_mesh,master,(FEM_Comm_t)comm);
00322 FEM_Mesh_deallocate(ow_mesh);
00323
00324 if (myRank==master && doWhat==FEM_MESH_UPDATE)
00325 nsw_mesh=FEM_Mesh_allocate();
00326
00327 FEM_Mesh_set_default_read(osr_mesh);
00328 FEM_Mesh_set_default_write(nsw_mesh);
00329 return (myRank==master);
00330 }
00331 void post(void) {
00332 if (doWhat==FEM_MESH_FINALIZE)
00333 MPI_Barrier(comm);
00334 if (osr_mesh>0) FEM_Mesh_deallocate(osr_mesh);
00335
00336 if (doWhat==FEM_MESH_UPDATE)
00337 {
00338 FEM_Mesh_deallocate(or_mesh);
00339 int nr_mesh=FEM_Mesh_broadcast(nsw_mesh,master,(FEM_Comm_t)comm);
00340 FEM_Mesh_set_default_read(nr_mesh);
00341 }
00342 else
00343 FEM_Mesh_set_default_read(or_mesh);
00344 FEM_Mesh_set_default_write(FEM_Mesh_allocate());
00345
00346 if (nsw_mesh>0) FEM_Mesh_deallocate(nsw_mesh);
00347 }
00348 };
00349
00350 CLINKAGE void FEM_Update_mesh(FEM_Update_mesh_fn callFn,int userValue,int doWhat)
00351 {
00352 updateState update(doWhat);
00353 if (update.pre() && 0 != userValue)
00354 (callFn)(userValue);
00355 update.post();
00356 }
00357
00358 FLINKAGE void FTN_NAME(FEM_UPDATE_MESH,fem_update_mesh)
00359 (FEM_Update_mesh_fortran_fn callFn,int *userValue,int *doWhat)
00360 {
00361 updateState update(*doWhat);
00362 if (update.pre() && (0 != *userValue))
00363 (callFn)(userValue);
00364 update.post();
00365 }
00366
00367
00368
00369
00370
00371 static int *splitMesh=NULL;
00372 static int splitChunks=0;
00373 CLINKAGE void FEM_Serial_split(int nchunks) {
00374 splitChunks=nchunks;
00375 splitMesh=new int[splitChunks];
00376 FEM_Mesh_partition(FEM_Mesh_default_write(),splitChunks,splitMesh);
00377 }
00378 FORTRAN_AS_C(FEM_SERIAL_SPLIT,FEM_Serial_split,fem_serial_split, (int *n),(*n))
00379
00380 CLINKAGE void FEM_Serial_begin(int chunkNo) {
00381 FEM_Mesh_write(splitMesh[chunkNo],"fem_mesh",chunkNo,splitChunks);
00382 FEM_Mesh_set_default_read(splitMesh[chunkNo]);
00383 }
00384 FORTRAN_AS_C(FEM_SERIAL_BEGIN,FEM_Serial_begin,fem_serial_begin, (int *c),(*c-1))
00385
00386
00387 CLINKAGE void FEM_Serial_read(int chunkNo,int nChunks) {
00388 if (splitMesh==NULL) {
00389 splitChunks=nChunks;
00390 splitMesh=new int[splitChunks];
00391 FEM_Mesh_deallocate(FEM_Mesh_default_write());
00392 }
00393 int readMesh=FEM_Mesh_read("fem_mesh",chunkNo,splitChunks);
00394 int writeMesh=FEM_Mesh_copy(readMesh);
00395 FEM_Mesh_become_set(writeMesh);
00396 splitMesh[chunkNo]=writeMesh;
00397 FEM_Mesh_deallocate(FEM_Mesh_default_read());
00398 FEM_Mesh_set_default_read(readMesh);
00399 FEM_Mesh_set_default_write(writeMesh);
00400 }
00401 FORTRAN_AS_C(FEM_SERIAL_READ,FEM_Serial_read,fem_serial_read, (int *c,int *n),(*c-1,*n))
00402
00403 CLINKAGE void FEM_Serial_assemble(void) {
00404 int serialMesh=FEM_Mesh_assemble(splitChunks,splitMesh);
00405 for (int i=0;i<splitChunks;i++)
00406 FEM_Mesh_deallocate(splitMesh[i]);
00407 FEM_Mesh_set_default_read(serialMesh);
00408 FEM_Mesh_set_default_write(FEM_Mesh_allocate());
00409 }
00410 FORTRAN_AS_C(FEM_SERIAL_ASSEMBLE,FEM_Serial_assemble,fem_serial_assemble,(void),())
00411
00412