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