/** Fill the node to element adjacency table for both this element and its corresponding ghosts */ void FEM_Node::setElemAdjacency(int type, const FEM_Elem &elem){ int nodesPerElem = elem.getNodesPer(); FEM_VarIndexAttribute *adjacencyAttr = elemAdjacency; CkVec<CkVec<ElemID> > &adjacencyTable = elemAdjacency->get(); FEM_VarIndexAttribute *ghostAdjacencyAttr = ((FEM_Node *)getGhost())->elemAdjacency; CkVec<CkVec<ElemID> > &ghostAdjacencyTable = ghostAdjacencyAttr->get(); // Scan through elements for(int i=0;i<elem.size();i++){ const int *conn = elem.connFor(i); for(int j=0;j<nodesPerElem;j++){ int node = conn[j]; if (node!=-1){ if(FEM_Is_ghost_index(node)){ int idx = ghostAdjacencyAttr->findInRow(FEM_To_ghost_index(node),var_id(type,i)); if(idx == -1) {// If not currently in the adjacency list, push onto list ghostAdjacencyTable[FEM_To_ghost_index(node)].push_back(var_id(type,i)); } } else{ int idx = adjacencyAttr->findInRow(node,var_id(type,i)); if(idx == -1) {// If not currently in the adjacency list, push onto list adjacencyTable[node].push_back(var_id(type,i)); } } } } } // Scan through ghost elements if(elem.getGhost()){ for(int i=0;i<((FEM_Elem*)elem.getGhost())->size();i++){ const int *conn = ((FEM_Elem*)elem.getGhost())->connFor(i); for(int j=0;j<nodesPerElem;j++){ int node = conn[j]; if (node!=-1){ if(FEM_Is_ghost_index(node)){ int idx = ghostAdjacencyAttr->findInRow(FEM_To_ghost_index(node),var_id(type,FEM_From_ghost_index(i))); if(idx == -1){ // If not currently in the adjacency list, push onto list ghostAdjacencyTable[FEM_To_ghost_index(node)].push_back(var_id(type,FEM_From_ghost_index(i))); } } else{ int idx = adjacencyAttr->findInRow(node,var_id(type,FEM_From_ghost_index(i))); if(idx == -1){// If not currently in the adjacency list, push onto list adjacencyTable[node].push_back(var_id(type,FEM_From_ghost_index(i))); } } } } } } }
/** Finds oldElem in n's element adjacency list, and replaces it with newElem */ void FEM_Mesh::n2e_replace(int n, int oldElem, int newElem) { if (n == -1) return; if(FEM_Is_ghost_index(n)){ FEM_VarIndexAttribute *eAdj = (FEM_VarIndexAttribute *)node.getGhost()->lookup(FEM_NODE_ELEM_ADJACENCY,"n2e_replace"); CkVec<CkVec<ElemID> > &eVec = eAdj->get(); CkVec<ElemID> &nsVec = eVec[FEM_To_ghost_index(n)]; for (int i=0; i<nsVec.length(); i++) { if (nsVec[i].getSignedId() == oldElem) { nsVec[i] = ElemID(0,newElem); break; } } int *testn2e, testn2ec; n2e_getAll(n,testn2e,testn2ec); for(int i=0; i<testn2ec; i++) { if(FEM_Is_ghost_index(testn2e[i])) CkAssert(elem[0].ghost->is_valid(FEM_From_ghost_index(testn2e[i]))); else CkAssert(elem[0].is_valid(testn2e[i])); } if(testn2ec!=0) delete[] testn2e; } else{ FEM_VarIndexAttribute *eAdj = (FEM_VarIndexAttribute *)node.lookup(FEM_NODE_ELEM_ADJACENCY,"n2e_replace"); CkVec<CkVec<ElemID> > &eVec = eAdj->get(); CkVec<ElemID> &nsVec = eVec[n]; for (int i=0; i<nsVec.length(); i++) { if (nsVec[i].getSignedId() == oldElem) { nsVec[i] = ElemID(0,newElem); break; } } } }
/** Adds newElem to node n's element adjacency list */ void FEM_Mesh::n2e_add(int n, int newElem) { if (n == -1) return; if(FEM_Is_ghost_index(n)){ FEM_VarIndexAttribute *eAdj = (FEM_VarIndexAttribute *)node.getGhost()->lookup(FEM_NODE_ELEM_ADJACENCY,"n2e_add"); CkVec<CkVec<ElemID> > &eVec = eAdj->get(); CkVec<ElemID> &nsVec = eVec[FEM_To_ghost_index(n)]; ElemID ne(0, newElem); nsVec.push_back(ne); int *testn2e, testn2ec; n2e_getAll(n,testn2e,testn2ec); for(int i=0; i<testn2ec; i++) { if(FEM_Is_ghost_index(testn2e[i])) CkAssert(elem[0].ghost->is_valid(FEM_From_ghost_index(testn2e[i]))); else CkAssert(elem[0].is_valid(testn2e[i])); } if(testn2ec!=0) delete[] testn2e; } else { FEM_VarIndexAttribute *eAdj = (FEM_VarIndexAttribute *)node.lookup(FEM_NODE_ELEM_ADJACENCY,"n2e_add"); CkVec<CkVec<ElemID> > &eVec = eAdj->get(); CkVec<ElemID> &nsVec = eVec[n]; ElemID ne(0, newElem); nsVec.push_back(ne); } }
void FEM_mesh_smooth(int mesh, int *nodes, int nNodes, int attrNo) { vector2d newPos, *coords, *ghostCoords,theCoord; int nNod, nGn, *boundVals, nodesInChunk; int neighbors[3], *adjnodes; int gIdxN; FEM_Mesh *meshP = FEM_Mesh_lookup(mesh, "driver"); nodesInChunk = FEM_Mesh_get_length(mesh,FEM_NODE); boundVals = new int[nodesInChunk]; nGn = FEM_Mesh_get_length(mesh, FEM_GHOST + FEM_NODE); coords = new vector2d[nodesInChunk+nGn]; FEM_Mesh_data(mesh, FEM_NODE, FEM_BOUNDARY, (int*) boundVals, 0, nodesInChunk, FEM_INT, 1); FEM_Mesh_data(mesh, FEM_NODE, attrNo, (double*)coords, 0, nodesInChunk, FEM_DOUBLE, 2); IDXL_Layout_t coord_layout = IDXL_Layout_create(IDXL_DOUBLE, 2); FEM_Update_ghost_field(coord_layout,-1, coords); ghostCoords = &(coords[nodesInChunk]); // FEM_Mesh_data(FEM_Mesh_default_write(), FEM_GHOST+FEM_NODE, attrNo, (double*)ghostCoords, 0, nGn, FEM_DOUBLE, 2); for (int i=0; i<nNodes; i++) { newPos.x=0; newPos.y=0; CkAssert(nodes[i]<nodesInChunk); if (FEM_is_valid(mesh, FEM_NODE, i) && boundVals[i]>-1) //node must be internal { meshP->n2n_getAll(i, &adjnodes, &nNod); // for (int j=0; j<nNod; j++) CkPrintf("node[%d]: %d\n", i,adjnodes[j]); for (int j=0; j<nNod; j++) { //for all adjacent nodes, find coords if (adjnodes[j]<-1) { gIdxN = FEM_From_ghost_index(adjnodes[j]); newPos.x += theCoord.x=ghostCoords[gIdxN].x; newPos.y += theCoord.y=ghostCoords[gIdxN].y; } else { newPos.x += theCoord.x=coords[adjnodes[j]].x; newPos.y += theCoord.y=coords[adjnodes[j]].y; } int rank=FEM_My_partition(); if (rank==0 && i==3 || rank==1 && i==17) { CkPrintf("node[%d]: %d\n", i,adjnodes[j]); CkPrintf("%d: (%f, %f)\n", j, theCoord.x, theCoord.y); } } newPos.x/=nNod; newPos.y/=nNod; FEM_set_entity_coord2(mesh, FEM_NODE, nodes[i], newPos.x, newPos.y); delete [] adjnodes; } } // FEM_Update_field(coord_layout, coords); // FEM_Mesh_data(FEM_Mesh_default_write(), FEM_NODE, attrNo, (double*)coords, 0, nodesInChunk, FEM_DOUBLE, 2); if (coords) delete [] coords; delete [] boundVals; }
/** createElemElemAdj() is similar to splitter::addTuple() * It will scan through all tuples/faces for each element * and register them with a tupleTable which will find * matching tuples between different elements. The matches * are then extracted from the table and the resulting * adjacencies are marked in the FEM_ELEM_ELEM_ADJACENCY * and FEM_ELEM_ELEM_ADJ_TYPES attribute fields. The attributes * store the adjacent element's local id and type respectively. * The ordering in the attribute tables is by local element id, * as usual, and is then ordered by the tuple ordering specified * in the last parameter to FEM_Add_elem2face_tuples, which * gets stored in the FEM_ElemAdj_Layer data structure * created/returned by getElemAdjLayer(). * * The element id's are NOT indices into the conn array in * the case of ghost elements. Ghost elements will have the * same element type as their corresponding real elements. * Their id, which gets stored in FEM_ELEM_ELEM_ADJACENCY * will be a negative number which can be converted to an index * with FEM_To_ghost_index(). Thus the user MUST use * FEM_Is_ghost_index(i) on the values, before accessing * them in the conn array, especially since the ghosts * will have a negative id. * * The function assumes that the FEM_ELEM_ELEM_ADJACENCY * and FEM_ELEM_ELEM_ADJ_TYPES attribute fields already exist. * * TODO: * * Verify the tuple table does not need to be * explicitly deleted. */ void FEM_Mesh::createElemElemAdj() { //CkPrintf("createElemElemAdj()\n"); FEM_ElemAdj_Layer *g = getElemAdjLayer(); if(! g->initialized) CkAbort("FEM> Cannot call FEM_Mesh_create_elem_elem_adjacency() before registering tuples with FEM_Add_elem2face_tuples()\n"); int nodesPerTuple = g->nodesPerTuple; tupleTable table(nodesPerTuple); // Put tuples into table for (int t=0;t<elem.size();t++){ // for each element type if(elem.hasNonEmpty(t)) { const int tuplesPerElem = g->elem[t].tuplesPerElem; const int numElements = elem[t].size(); // for every element of type t: for (int elemIndex=0;elemIndex<numElements;elemIndex++) { // insert element into the tuple table const int *conn=elem[t].connFor(elemIndex); int tuple[tupleTable::MAX_TUPLE]; FEM_Symmetries_t allSym; // copy node numbers into tuple for (int u=0;u<tuplesPerElem;u++) { for (int i=0;i<nodesPerTuple;i++) { int eidx=g->elem[t].elem2tuple[i+u*g->nodesPerTuple]; if (eidx==-1) // "not-there" node tuple[i]=-1; // Don't map via connectivity else // Ordinary node tuple[i]=conn[eidx]; } // add tuple to table table.addTuple(tuple,new elemList(0,elemIndex,t,allSym,u)); } } // Put corresponding ghost elements into tuple table if(elem[t].getGhost() != NULL){ FEM_Elem *ghostElem = (FEM_Elem *)elem[t].getGhost(); const int numElements = ghostElem->size(); // for every element of type t: for (int elemIndex=0;elemIndex<numElements;elemIndex++) { // insert element into the tuple table const int *conn=ghostElem->connFor(elemIndex); int tuple[tupleTable::MAX_TUPLE]; FEM_Symmetries_t allSym; // copy node numbers into tuple for (int u=0;u<tuplesPerElem;u++) { for (int i=0;i<nodesPerTuple;i++) { int eidx=g->elem[t].elem2tuple[i+u*g->nodesPerTuple]; if (eidx==-1) { //"not-there" node-- tuple[i]=-1; //Don't map via connectivity } else { //Ordinary node int n=conn[eidx]; tuple[i]=n; } } // add tuple to table table.addTuple(tuple,new elemList(0,FEM_From_ghost_index(elemIndex),t,allSym,u)); } } } } } /* Extract adjacencies from table and store into * FEM_ELEM_ELEM_ADJACENCY and FEM_ELEM_ELEM_ADJ_TYPES * attribute fields */ for (int t=0;t<elem.size();t++) { // for each element type t if (elem.hasNonEmpty(t)) { elemList *l; const int tuplesPerElem = g->elem[t].tuplesPerElem; const int numElements = elem[t].size(); const int numGhostElements = ((FEM_Elem*)(elem[t].getGhost()))->size(); // directly modify the element adjacency table for element type t FEM_IndexAttribute *elemAdjTypesAttr = (FEM_IndexAttribute *)elem[t].lookup(FEM_ELEM_ELEM_ADJ_TYPES,"createElemElemAdj"); FEM_IndexAttribute *elemAdjAttr = (FEM_IndexAttribute *)elem[t].lookup(FEM_ELEM_ELEM_ADJACENCY,"createElemElemAdj"); FEM_IndexAttribute *elemAdjTypesAttrGhost = (FEM_IndexAttribute *)elem[t].getGhost()->lookup(FEM_ELEM_ELEM_ADJ_TYPES,"createElemElemAdj"); FEM_IndexAttribute *elemAdjAttrGhost = (FEM_IndexAttribute *)elem[t].getGhost()->lookup(FEM_ELEM_ELEM_ADJACENCY,"createElemElemAdj"); CkAssert(elemAdjTypesAttr && elemAdjAttr); AllocTable2d<int> &adjTable = elemAdjAttr->get(); int *adjs = adjTable.getData(); AllocTable2d<int> &adjTypesTable = elemAdjTypesAttr->get(); int *adjTypes = adjTypesTable.getData(); AllocTable2d<int> &adjTableGhost = elemAdjAttrGhost->get(); int *adjsGhost = adjTableGhost.getData(); AllocTable2d<int> &adjTypesTableGhost = elemAdjTypesAttrGhost->get(); int *adjTypesGhost = adjTypesTableGhost.getData(); // initialize tables for(int i=0;i<numElements*tuplesPerElem;i++){ adjs[i]=-1; adjTypes[i]=-1; } for(int i=0;i<numGhostElements*tuplesPerElem;i++){ adjsGhost[i]=-1; adjTypesGhost[i]=-1; } // look through each elemList that is returned by the tuple table table.beginLookup(); while (NULL!=(l=table.lookupNext())) { if (l->next==NULL) { // One-entry list: must be a symmetry // UNHANDLED CASE: not sure exactly what this means } else { /* Several elements in list: normal case */ //CkPrintf("Found in table list: "); //for(const elemList *c=l;c!=NULL;c=c->next){ // CkPrintf(" %d,%d", c->type, c->localNo); //} //CkPrintf("\n"); // for each a,b from the list for (const elemList *a=l;a!=NULL;a=a->next){ for (const elemList *b=l;b!=NULL;b=b->next){ // if a and b are different elements if((a->localNo != b->localNo) || (a->type != b->type)){ int j; if(a->type == t){ // only update the entries for element type t if(FEM_Is_ghost_index(a->localNo)){ j = FEM_To_ghost_index(a->localNo)*tuplesPerElem + a->tupleNo; CkAssert(j<numGhostElements*tuplesPerElem); adjsGhost[j] = b->localNo; adjTypesGhost[j] = b->type; } else { j = a->localNo*tuplesPerElem + a->tupleNo; CkAssert(j<numElements*tuplesPerElem); //CkPrintf("Recording that %d,%d at position %d has neighbor %d,%d \n", a->type,a->localNo, a->tupleNo, b->type, b->localNo); adjs[j] = b->localNo; adjTypes[j] = b->type; } } } } } } } } } }
void FEM_mesh_smooth(int mesh, int *nodes, int nNodes, int attrNo) { vector3d *centroids, newPos, *coords, *ghostCoords, *vGcoords; int nEle, nGn, *boundVals, nodesInChunk, nVg; int neighbors[3], *adjelems; int gIdxN; int j=0; double x[3], y[3]; FEM_Mesh *meshP = FEM_Mesh_lookup(mesh, "driver"); nodesInChunk = FEM_Mesh_get_length(mesh,FEM_NODE); boundVals = new int[nodesInChunk]; nGn = FEM_Mesh_get_length(mesh, FEM_GHOST + FEM_NODE); coords = new vector3d[nodesInChunk+nGn]; FEM_Mesh_data(mesh, FEM_NODE, FEM_BOUNDARY, (int*) boundVals, 0, nodesInChunk, FEM_INT, 1); FEM_Mesh_data(mesh, FEM_NODE, attrNo, (double*)coords, 0, nodesInChunk, FEM_DOUBLE, 2); for (int i=0; i<(nodesInChunk); i++) { //CkPrintf(" coords[%d]: (%f, %f)\n", i, coords[i].x, coords[i].y); } IDXL_Layout_t coord_layout = IDXL_Layout_create(IDXL_DOUBLE, 2); FEM_Update_ghost_field(coord_layout,-1, coords); ghostCoords = &(coords[nodesInChunk]); /* for (int i=0; i<nGn;i++) { if (FEM_is_valid(mesh, FEM_GHOST+FEM_NODE, i)) { CkPrintf("ghost %d is valid \n", i); // vGcoords[j]=ghostCoords[i]; //j++; } else CkPrintf("ghost %d is invalid \n", i); } */ for (int i=0; i<(nodesInChunk+nGn); i++) { //CkPrintf(" coords[%d]: (%f, %f)\n", i, coords[i].x, coords[i].y); } // FEM_Mesh_data(FEM_Mesh_default_write(), FEM_GHOST+FEM_NODE, attrNo, (double*)ghostCoords, 0, nGn, FEM_DOUBLE, 2); for (int i=0; i<nNodes; i++) { newPos.x=0; newPos.y=0; CkAssert(nodes[i]<nodesInChunk); if (FEM_is_valid(mesh, FEM_NODE, i) && boundVals[i]>-1) //node must be internal { meshP->n2e_getAll(i, &adjelems, &nEle); centroids = new vector3d[nEle]; for (int j=0; j<nEle; j++) { //for all adjacent elements, find centroids meshP->e2n_getAll(adjelems[j], neighbors); for (int k=0; k<3; k++) { if (neighbors[k]<-1) { gIdxN = FEM_From_ghost_index(neighbors[k]); x[k] = ghostCoords[gIdxN].x; y[k] = ghostCoords[gIdxN].y; } else { x[k] = coords[neighbors[k]].x; y[k] = coords[neighbors[k]].y; } } centroids[j].x=(x[0]+x[1]+x[2])/3.0; centroids[j].y=(y[0]+y[1]+y[2])/3.0; newPos.x += centroids[j].x; newPos.y += centroids[j].y; } newPos.x/=nEle; newPos.y/=nEle; FEM_set_entity_coord2(mesh, FEM_NODE, nodes[i], newPos.x, newPos.y); delete [] centroids; delete [] adjelems; } } delete [] coords; delete [] boundVals; }