// A driver() function // driver() is required in all FEM programs extern "C" void driver(void) { int nnodes,nelems,nelems2,ignored; int i, myId=FEM_My_partition(); myGlobals g; FEM_Register(&g,(FEM_PupFn)pup_myGlobals); _registerFEMMeshModify(); printf("partition %d is in driver\n", myId); int mesh=FEM_Mesh_default_read(); // Tell framework we are reading data from the mesh // Get node data nnodes=FEM_Mesh_get_length(mesh,FEM_NODE); // Get number of nodes g.nnodes=nnodes; g.coord=new vector3d[nnodes]; // Get node positions FEM_Mesh_data(mesh, FEM_NODE, FEM_DATA+0, (double*)g.coord, 0, nnodes, FEM_DOUBLE, 3); // Get element data nelems=FEM_Mesh_get_length(mesh,FEM_ELEM+0); // Get number of elements g.nelems=nelems; g.conn=new connRec[nelems]; // Get connectivity for elements FEM_Mesh_data(mesh, FEM_ELEM+0, FEM_CONN, (int *)g.conn, 0, nelems, FEM_INDEX_0, 4); double* tridata =new double[nelems]; FEM_Mesh_data(mesh, FEM_ELEM+0, FEM_DATA, (int *)tridata, 0, nelems, FEM_DOUBLE, 1); int nelemsghost=FEM_Mesh_get_length(mesh,FEM_ELEM+0+FEM_GHOST); double* trighostdata =new double[nelemsghost]; FEM_Mesh_data(mesh, FEM_ELEM+0+FEM_GHOST, FEM_DATA, (int *)trighostdata, 0, nelemsghost, FEM_DOUBLE, 1); int nnodesghost=FEM_Mesh_get_length(mesh,FEM_NODE+0+FEM_GHOST); double* nodeghostdata =new double[3*nnodesghost]; FEM_Mesh_data(mesh, FEM_NODE+0+FEM_GHOST, FEM_DATA, (int *)nodeghostdata, 0, nnodesghost, FEM_DOUBLE, 3); { const int triangleFaces[12] = {0,1,2,1,2,3,2,3,0,0,3,1}; FEM_Add_elem2face_tuples(mesh, 0, 3, 4, triangleFaces); FEM_Mesh_create_elem_elem_adjacency(mesh); FEM_Mesh_allocate_valid_attr(mesh, FEM_ELEM+0); FEM_Mesh_allocate_valid_attr(mesh, FEM_NODE); FEM_Mesh_create_node_elem_adjacency(mesh); FEM_Mesh_create_node_node_adjacency(mesh); int netIndex = 0; publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif int rank = 0; MPI_Comm comm = MPI_COMM_WORLD; MPI_Comm_rank(comm,&rank); MPI_Barrier(comm); FEM_REF_INIT(mesh); FEM_Mesh *meshP = FEM_Mesh_lookup(FEM_Mesh_default_read(),"driver"); FEM_AdaptL *ada = meshP->getfmMM()->getfmAdaptL(); int ret_op = -1; FEM_Adapt_Algs *adaptAlgs= meshP->getfmMM()->getfmAdaptAlgs(); adaptAlgs->FEM_Adapt_Algs_Init(FEM_DATA+0,FEM_DATA+4); FEM_Interpolate *interp = meshP->getfmMM()->getfmInp(); //interp->FEM_SetInterpolateNodeEdgeFnPtr(interpolate); MPI_Barrier(comm); //CkPrintf("Shadow arrays have been bound\n"); /* #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif CkPrintf("Marking 5 nodes and one element as invalid\n"); FEM_set_entity_invalid(mesh, FEM_NODE, 5); FEM_set_entity_invalid(mesh, FEM_NODE, 6); FEM_set_entity_invalid(mesh, FEM_NODE, 7); FEM_set_entity_invalid(mesh, FEM_NODE, 8); FEM_set_entity_invalid(mesh, FEM_NODE, 9); FEM_set_entity_invalid(mesh, FEM_ELEM, 9); #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif CkPrintf("Marking 5 nodes and one element as valid again\n"); FEM_set_entity_valid(mesh, FEM_NODE, 5); FEM_set_entity_valid(mesh, FEM_NODE, 6); FEM_set_entity_valid(mesh, FEM_NODE, 7); FEM_set_entity_valid(mesh, FEM_NODE, 8); FEM_set_entity_valid(mesh, FEM_NODE, 9); FEM_set_entity_valid(mesh, FEM_ELEM, 9); */ #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif int adjs[4]; int elemid; if(rank == 0) { adjs[0] = 0; adjs[1] = 1; adjs[2] = 2; adjs[3] = 3; elemid = 0; } else if(rank == 1) { adjs[0] = 19; adjs[1] = 5; adjs[2] = 7; adjs[3] = 21; elemid = 21; } else if(rank == 2) { adjs[0] = 8; adjs[1] = 11; adjs[2] = 6; adjs[3] = 21; elemid = 7; } else { adjs[0] = 0; adjs[1] = 1; adjs[2] = 2; adjs[3] = 3; elemid = 0; } int newel1 = 0; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); FEM_Print_n2e(mesh,adjs[0]); FEM_Print_n2e(mesh,adjs[1]); FEM_Print_n2e(mesh,adjs[2]); FEM_Print_n2e(mesh,adjs[3]); FEM_Print_n2n(mesh,adjs[0]); FEM_Print_n2n(mesh,adjs[1]); FEM_Print_n2n(mesh,adjs[2]); FEM_Print_n2n(mesh,adjs[3]); FEM_Print_e2n(mesh,elemid); FEM_Print_e2e(mesh,elemid); #endif //FEM_Modify_Lock(mesh, adjs, 3, adjs, 0); if(rank == 0) { FEM_remove_element(mesh, elemid, 0, 1); } //FEM_Modify_Unlock(mesh); MPI_Barrier(comm); #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif //FEM_Modify_Lock(mesh, adjs, 3, adjs, 0); if(rank == 0) { newel1 = FEM_add_element(mesh,adjs,4,0,0); CkPrintf("New Element\n"); } //FEM_Modify_Unlock(mesh); publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); FEM_Print_n2e(mesh,adjs[0]); FEM_Print_n2e(mesh,adjs[1]); FEM_Print_n2e(mesh,adjs[2]); FEM_Print_n2e(mesh,adjs[3]); FEM_Print_n2n(mesh,adjs[0]); FEM_Print_n2n(mesh,adjs[1]); FEM_Print_n2n(mesh,adjs[2]); FEM_Print_n2n(mesh,adjs[3]); FEM_Print_e2n(mesh,newel1); FEM_Print_e2e(mesh,newel1); #endif /* if(rank==0){ FEM_Print_Mesh_Summary(mesh); CkPrintf("%d: Removing element \n", rank); int nelemsghost =FEM_Mesh_get_length(mesh,FEM_ELEM+0+FEM_GHOST); int numvalidghost =FEM_count_valid(mesh,FEM_ELEM+0+FEM_GHOST); CkPrintf("nelemsghost=%d numvalidghost=%d\n", nelemsghost, numvalidghost); for(int i=1;i<20;i++){ if(FEM_is_valid(mesh, FEM_ELEM+FEM_GHOST, i)){ double data[1]; FEM_Mesh_data(mesh, FEM_ELEM+FEM_GHOST, FEM_DATA, (int *)data, i, 1, FEM_DOUBLE, 1); CkPrintf("%d: Eating ghost element %d with value %f\n", rank, i, data[1]); int conn[3]; FEM_Mesh_data(mesh, FEM_ELEM+FEM_GHOST, FEM_CONN, (int *)conn, i, 1, FEM_INDEX_0, 3); CkPrintf("conn for element is: %d %d %d\n", conn[0], conn[1], conn[2]); FEM_Modify_Lock(mesh, conn, 3, conn, 0); FEM_remove_element(mesh, FEM_From_ghost_index(i), 0, 1); FEM_Modify_Unlock(mesh); MPI_Barrier(comm); FEM_Print_Mesh_Summary(mesh); FEM_Modify_Lock(mesh, conn, 3, conn, 0); FEM_add_element(mesh, conn, 3, 0, rank); // add locally FEM_Modify_Unlock(mesh); CkPrintf("New conn for element is: %d %d %d\n", conn[0], conn[1], conn[2]); publish_data_netfem(netIndex,g); netIndex++; FEM_Print_Mesh_Summary(mesh); } else{ // CkPrintf("invalid element %d\n", i); } } } else { CkPrintf("Rank %d\n", rank); for(int i=1;i<20;i++){ MPI_Barrier(comm); FEM_Print_Mesh_Summary(mesh); publish_data_netfem(netIndex,g); netIndex++; FEM_Print_Mesh_Summary(mesh); } } publish_data_netfem(netIndex,g); netIndex++; */ /* CkPrintf("Starting Local edge flips on individual chunks\n"); int flip[4]; if(rank == 0) { flip[0] = 1; flip[1] = 2; flip[2] = 0; flip[3] = 3; } else if(rank == 1) { flip[0] = 1; flip[1] = 2; flip[2] = 0; flip[3] = 4; } else if(rank == 2) { flip[0] = 13; flip[1] = 14; flip[2] = 15; flip[3] = 7; } else { flip[0] = 0; flip[1] = 1; flip[2] = 2; flip[3] = 3; } #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif ret_op = ada->edge_flip(flip[0],flip[1]); publish_data_netfem(netIndex,g); netIndex++; ret_op = ada->edge_flip(flip[2],flip[3]); publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif CkPrintf("Starting shared edge flips on individual chunks\n"); int sflip[4]; if(rank == 0) { sflip[0] = 19; sflip[1] = 18; sflip[2] = 1; sflip[3] = -4; } else if(rank == 1) { sflip[0] = 5; sflip[1] = 6; sflip[2] = 7; sflip[3] = -5; } else if(rank == 2) { sflip[0] = 11; sflip[1] = 2; sflip[2] = 0; sflip[3] = -2; } else { sflip[0] = 0; sflip[1] = 1; sflip[2] = 2; sflip[3] = 3; } #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif ret_op = ada->edge_flip(sflip[0],sflip[1]); publish_data_netfem(netIndex,g); netIndex++; if(ret_op > 0) { if(sflip[2]<0) sflip[2] = ret_op; else if(sflip[3]<0) sflip[3] = ret_op; } ret_op = ada->edge_flip(sflip[2],sflip[3]); publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif CkPrintf("Starting Local edge bisect on individual chunks\n"); int bisect[2]; if(rank == 0) { bisect[0] = 16; bisect[1] = 21; } else if(rank == 1) { bisect[0] = 5; bisect[1] = 6; } else if(rank == 2) { bisect[0] = 8; bisect[1] = 11; } else { bisect[0] = 0; bisect[1] = 1; } if(rank==2) ret_op = ada->edge_bisect(bisect[0],bisect[1]); publish_data_netfem(netIndex,g); netIndex++; adaptAlgs->tests(); MPI_Barrier(comm); #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif CkPrintf("Starting Local vertex remove on individual chunks\n"); int vr[2]; if(rank == 0) { vr[0] = ret_op; vr[1] = 6; } else if(rank == 1) { vr[0] = ret_op; vr[1] = 13; } else if(rank == 2) { vr[0] = ret_op; vr[1] = 21; } else { vr[0] = ret_op; vr[1] = 1; } #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif ret_op = ada->vertex_remove(vr[0],vr[1]); publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif CkPrintf("Starting shared edge bisect on individual chunks\n"); int sbisect[2]; if(rank == 0) { sbisect[0] = 1;//4;//21; sbisect[1] = 19;//20; } else if(rank == 1) { sbisect[0] = 0; sbisect[1] = 21; } else if(rank == 2) { sbisect[0] = 20;//9;//3; sbisect[1] = 8;//2;//19; } else { sbisect[0] = 0; sbisect[1] = 1; } #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif ret_op = ada->edge_bisect(sbisect[0],sbisect[1]); publish_data_netfem(netIndex,g); netIndex++; CkPrintf("Starting shared vertex remove on individual chunks\n"); int svr[2]; if(rank == 0) { svr[0] = ret_op; svr[1] = 19; } else if(rank == 1) { svr[0] = ret_op; svr[1] = 21; } else if(rank == 2) { svr[0] = ret_op; svr[1] = 20; } else { svr[0] = ret_op; svr[1] = 1; } #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif ret_op = ada->vertex_remove(svr[0],svr[1]); publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif CkPrintf("Starting Local edge contract on individual chunks\n"); int contract[2]; if(rank == 0) { contract[1] = 16; contract[0] = 21; } else if(rank == 1) { contract[0] = 5; contract[1] = 6; } else if(rank == 2) { contract[0] = 19; contract[1] = 17; } else { contract[0] = 0; contract[1] = 1; } #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif if(rank==0) ret_op = ada->edge_contraction(contract[0],contract[1]); publish_data_netfem(netIndex,g); netIndex++; //CkPrintf("Starting Local vertex split on individual chunks\n"); /* int vs[3]; if(rank == 0) { vs[0] = ret_op; vs[1] = 9; vs[2] = 13; } else if(rank == 1) { vs[0] = ret_op; vs[1] = 8; vs[2] = 7; } else if(rank == 2) { vs[0] = ret_op; vs[1] = 14; vs[2] = 23; } else { vs[0] = ret_op; vs[1] = 2; vs[2] = 3; } #ifdef SUMMARY_ON //FEM_Print_Mesh_Summary(mesh); #endif //ret_op = ada->vertex_split(vs[0],vs[1],vs[2]); //publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif */ /* CkPrintf("Starting shared edge contract on individual chunks\n"); int scontract[2]; if(rank == 0) { scontract[0] = 9; scontract[1] = 10; } else if(rank == 1) { scontract[0] = 5; scontract[1] = 6; } else if(rank == 2) { scontract[0] = 11; scontract[1] = 2; } else { scontract[0] = 0; scontract[1] = 1; } #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif ret_op = ada->edge_contraction(scontract[0],scontract[1]); publish_data_netfem(netIndex,g); netIndex++; /* //CkPrintf("Starting shared vertex split on individual chunks\n"); int svs[3]; if(rank == 0) { svs[0] = ret_op; svs[1] = 1; svs[2] = -6; } else if(rank == 1) { svs[0] = ret_op; svs[1] = 7; svs[2] = 7; } else if(rank == 2) { svs[0] = ret_op; svs[1] = 0; svs[2] = -2; } else { svs[0] = ret_op; svs[1] = 2; svs[2] = 3; } #ifdef SUMMARY_ON //FEM_Print_Mesh_Summary(mesh); #endif //ret_op = ada->vertex_split(svs[0],svs[1],svs[2]); //publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif */ /* CkPrintf("Starting LEB on individual chunks\n"); int *leb_elem = (int*)malloc(1*sizeof(int)); if(rank==0) { leb_elem[0] = 2; } else if(rank==1) { leb_elem[0] = 13; //4; } else if(rank==2) { leb_elem[0] = 20; //26; } else if (rank == 3){ leb_elem[0] = 14; } else { leb_elem[0] = 0; } adaptAlgs->refine_element_leb(leb_elem[0]); publish_data_netfem(netIndex,g); netIndex++; */ /* int nEle; //for(int tstep = 0; tstep < 2; tstep++) { nEle = FEM_Mesh_get_length(mesh, FEM_ELEM); for (int i=0; i<nEle; i++) if (FEM_is_valid(mesh, FEM_ELEM, i)) adaptAlgs->refine_element_leb(i); publish_data_netfem(netIndex,g); netIndex++; FEM_Print_Mesh_Summary(mesh); //} */ double targetArea = 0.00004; for(int tstep = 0; tstep < 0; tstep++) { adaptAlgs->simple_refine(targetArea); publish_data_netfem(netIndex,g); netIndex++; adaptAlgs->tests(); MPI_Barrier(comm); //int *nodes = new int[g.nnodes]; //for (int i=0; i<g.nnodes; i++) nodes[i]=i; //FEM_mesh_smooth(mesh, nodes, g.nnodes, FEM_DATA+0); //publish_data_netfem(netIndex,g); netIndex++; //delete [] nodes; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif adaptAlgs->simple_coarsen(targetArea); publish_data_netfem(netIndex,g); netIndex++; adaptAlgs->tests(); MPI_Barrier(comm); //int *nodes = new int[g.nnodes]; //for (int i=0; i<g.nnodes; i++) nodes[i]=i; //FEM_mesh_smooth(mesh, nodes, g.nnodes, FEM_DATA+0); //publish_data_netfem(netIndex,g); netIndex++; //delete [] nodes; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif } targetArea = 0.00004; for(int tstep = 0; tstep < 0; tstep++) { adaptAlgs->simple_refine(targetArea); publish_data_netfem(netIndex,g); netIndex++; adaptAlgs->tests(); MPI_Barrier(comm); //int *nodes = new int[g.nnodes]; //for (int i=0; i<g.nnodes; i++) nodes[i]=i; //FEM_mesh_smooth(mesh, nodes, g.nnodes, FEM_DATA+0); //publish_data_netfem(netIndex,g); netIndex++; //delete [] nodes; targetArea *= 0.5; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif } targetArea /= 0.4; for(int tstep = 0; tstep < 0; tstep++) { adaptAlgs->simple_coarsen(targetArea); publish_data_netfem(netIndex,g); netIndex++; adaptAlgs->tests(); MPI_Barrier(comm); //int *nodes = new int[g.nnodes]; //for (int i=0; i<g.nnodes; i++) nodes[i]=i; //FEM_mesh_smooth(mesh, nodes, g.nnodes, FEM_DATA+0); //publish_data_netfem(netIndex,g); netIndex++; //delete [] nodes; targetArea *= 1.5; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif } //wave propagation on a bar targetArea = 0.00004; double xmin = 0.00; double xmax = 0.1; double ymin = 0.00; double ymax = 0.01; for(int tstep = 0; tstep < 0; tstep++) { targetArea = 0.000002; adaptAlgs->simple_refine(targetArea, xmin, ymin, xmax, ymax); publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif targetArea = 0.0000014; adaptAlgs->simple_coarsen(targetArea, xmin, ymin, xmax, ymax); publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif ymin += 0.01; ymax += 0.01; } //crack propagation on a block targetArea = 0.00004; xmin = 0.00; xmax = 0.2; double xcrackmin = 0.09; double xcrackmax = 0.10; ymin = 0.00; ymax = 0.02; for(int tstep = 0; tstep < 0; tstep++) { targetArea = 0.000025; adaptAlgs->simple_refine(targetArea, xmin, ymin, xmax, ymax); publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif targetArea = 0.00005; adaptAlgs->simple_coarsen(targetArea, xmin, ymin, xmax, ymax); //publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif /*if(tstep > 2) { targetArea = 0.000025; adaptAlgs->simple_refine(targetArea, xcrackmin, ymin, xcrackmax, ymax); //publish_data_netfem(netIndex,g); netIndex++; #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif xcrackmin -= 0.004; xcrackmax += 0.004; } */ ymin += 0.02; ymax += 0.02; } CkPrintf("chunk %d Waiting for Synchronization\n",rank); MPI_Barrier(comm); CkPrintf("Synchronized\n"); #ifdef SUMMARY_ON FEM_Print_Mesh_Summary(mesh); #endif publish_data_netfem(netIndex,g); netIndex++; CkExit(); } }
int FEM_Adapt::vertex_split_help(int n, int n1, int n2, int e1, int e3) { int e1_n = find_local_node_index(e1, n); int e1_n1 = find_local_node_index(e1, n1); int e2 = theMesh->e2e_getNbr(e1, get_edge_index(e1_n, e1_n1)); int e3_n = find_local_node_index(e3, n); int e3_n2 = find_local_node_index(e3, n2); int e4 = theMesh->e2e_getNbr(e3, get_edge_index(e3_n, e3_n2)); if (!check_orientation(e1, e3, n, n1, n2)) { int tmp = e3; e3 = e4; e4 = tmp; e3_n = find_local_node_index(e3, n); e3_n2 = find_local_node_index(e3, n2); } int locknodes[4]; locknodes[0] = n1; locknodes[1] = n; locknodes[2] = n2; locknodes[3] = -1; int lockelems[6]; lockelems[0] = e1; lockelems[1] = e2; lockelems[2] = e3; lockelems[3] = e4; lockelems[4] = -1; lockelems[5] = -1; int elemConn[3]; //FEM_Modify_Lock(theMesh, locknodes, 4, lockelems, 6); #ifdef DEBUG_1 CkPrintf("Vertex Split, %d-%d-%d on chunk %d\n", n1, n, n2, theMod->getfmUtil()->getIdx()); #endif int adjnodes[2]; adjnodes[0] = n; //looks like it will never be shared, since according to later code, all n1, n & n2 should be local.. appears to be not correct //the new node will be shared to wahtever the old node was shared to, we'll do this later int *chunks = NULL; int numChunks = 0; int np = FEM_add_node(theMesh,adjnodes,1,chunks,numChunks,0); locknodes[3] = np; int current, next, nt, nl, eknp, eknt, eknl; // traverse elements on one side of n starting with e2 current = e2; nt = n1; while ((current != e3) && (current != -1)) { eknp = find_local_node_index(current, n); eknt = find_local_node_index(current, nt); eknl = 3 - eknp - eknt; next = theMesh->e2e_getNbr(current, get_edge_index(eknp, eknl)); nl = theMesh->e2n_getNode(current, eknl); FEM_remove_element(theMesh, current, 0); // add nl, nt, np elemConn[eknp] = np; elemConn[eknt] = nt; elemConn[eknl] = nl; int newelem = FEM_add_element(theMesh, elemConn, 3, 0); nt = nl; current = next; } if (current == -1) { // didn't make it all the way around // traverse elements on one side of n starting with e4 current = e4; nt = n2; while ((current != e1) && (current != -1)) { eknp = find_local_node_index(current, n); eknt = find_local_node_index(current, nt); eknl = 3 - eknp - eknt; next = theMesh->e2e_getNbr(current, get_edge_index(eknp, eknl)); nl = theMesh->e2n_getNode(current, eknl); FEM_remove_element(theMesh, current, 0); // add nl, nt, np elemConn[eknp] = np; elemConn[eknt] = nt; elemConn[eknl] = nl; int newelem = FEM_add_element(theMesh, elemConn, 3, 0); nt = nl; current = next; } } // add n, n1, np elemConn[e1_n] = n; elemConn[e1_n1] = n1; elemConn[3 - e1_n - e1_n1] = np; lockelems[4] = FEM_add_element(theMesh, elemConn, 3, 0); // add n, n2, np elemConn[e3_n] = n; elemConn[e3_n2] = n2; elemConn[3 - e3_n - e3_n2] = np; lockelems[5] = FEM_add_element(theMesh, elemConn, 3, 0); return np; }
/** Given edge e:(n1, n2), remove the two elements (n1,n2,n3) and (n2,n1,n4) adjacent to e, and bisect e by adding node n5. Add elements (n1,n5,n3), (n5,n2,n3), (n5,n1,n4) and (n2,n5,n4); returns new node n5. n3 n3 o o / \ /|\ / \ / | \ / \ / | \ / \ / |n5 \ n1 o---------o n2 n1 o----o----o n2 \ / \ | / \ / \ | / \ / \ | / \ / \|/ o o n4 n4 */ int FEM_Adapt::edge_bisect_help(int e1, int e2, int n1, int n2, int e1_n1, int e1_n2, int e1_n3, int e2_n1, int e2_n2, int e2_n3, int n3, int n4) { int n5; int numNodes = 4; int numElems = 2; int numNodesNew = 5; int numElemsNew = 4; int locknodes[5]; int lockelems[4]; int elemConn[3]; locknodes[0] = n1; locknodes[1] = n2; locknodes[2] = n3; locknodes[3] = n4; locknodes[4] = -1; lockelems[0] = e1; lockelems[1] = e2; lockelems[2] = -1; lockelems[3] = -1; //FEM_Modify_Lock(theMesh, locknodes, numNodes, lockelems, numElems); int e1chunk=-1, e2chunk=-1, e3chunk=-1, e4chunk=-1, n5chunk=-1; int index = theMod->getIdx(); #ifdef DEBUG_1 CkPrintf("Bisect edge %d->%d on chunk %d\n", n1, n2, theMod->getfmUtil()->getIdx()); #endif //verify quality bool flag = theMod->fmAdaptAlgs->controlQualityR(n1,n2,n3,n4); if(flag) return -1; //add node if(e1==-1) e1chunk=-1; else if(e1>=0) e1chunk=index; else { int ghostid = FEM_To_ghost_index(e1); const IDXL_Rec *irec = theMesh->elem[0].ghost->ghostRecv.getRec(ghostid); CkAssert(irec->getShared()==1); e1chunk = irec->getChk(0); } if(e2==-1) e2chunk=-1; else if(e2>=0) e2chunk=index; else { int ghostid = FEM_To_ghost_index(e2); const IDXL_Rec *irec = theMesh->elem[0].ghost->ghostRecv.getRec(ghostid); CkAssert(irec->getShared()==1); e2chunk = irec->getChk(0); } int adjnodes[2]; adjnodes[0] = n1; adjnodes[1] = n2; int *chunks; int numChunks=0; int forceshared = 0; if(e1chunk==e2chunk || (e1chunk==-1 || e2chunk==-1)) { forceshared = -1; numChunks = 1; chunks = new int[1]; if(e1chunk!=-1) chunks[0] = e1chunk; else chunks[0] = e2chunk; } else { numChunks = 2; chunks = new int[2]; chunks[0] = e1chunk; chunks[1] = e2chunk; } n5 = FEM_add_node(theMesh,adjnodes,2,chunks,numChunks,forceshared); delete[] chunks; //lock this node immediately FEM_Modify_LockN(theMesh, n5, 0); //remove elements e1chunk = FEM_remove_element(theMesh, e1, 0); e2chunk = FEM_remove_element(theMesh, e2, 0); // assumes intelligent behavior when no e2 exists // hmm... if e2 is a ghost and we remove it and create all the new elements // locally, then we don't really need to add a *shared* node //but we are not moving chunk boundaries for bisect if(e1chunk==-1 || e2chunk==-1) { //it is fine, let it continue e4chunk = e2chunk; e3chunk = e1chunk; } else if(e1chunk==e2chunk && e1chunk!=index) { n5chunk = e1chunk; e4chunk = e2chunk; e3chunk = e1chunk; } else { //there can be a lot of conditions, but we do not have to do aything special now n5chunk = -1; e4chunk = e2chunk; e3chunk = e1chunk; } // add n1, n5, n3 elemConn[e1_n1] = n1; elemConn[e1_n2] = n5; elemConn[e1_n3] = n3; lockelems[0] = FEM_add_element(theMesh, elemConn, 3, 0, e1chunk); theMod->fmUtil->copyElemData(0,e1,lockelems[0]); // add n2, n5, n3 elemConn[e1_n1] = n5; elemConn[e1_n2] = n2; elemConn[e1_n3] = n3; lockelems[1] = FEM_add_element(theMesh, elemConn, 3, 0, e3chunk); theMod->fmUtil->copyElemData(0,e1,lockelems[1]); if (e2 != -1) { // e2 exists // add n1, n5, n4 elemConn[e2_n1] = n1; elemConn[e2_n2] = n5; elemConn[e2_n3] = n4; lockelems[2] = FEM_add_element(theMesh, elemConn, 3, 0, e2chunk); theMod->fmUtil->copyElemData(0,e2,lockelems[2]); // add n2, n5, n4 elemConn[e2_n1] = n5; elemConn[e2_n2] = n2; elemConn[e2_n3] = n4; lockelems[3] = FEM_add_element(theMesh, elemConn, 3, 0, e4chunk); theMod->fmUtil->copyElemData(0,e2,lockelems[3]); } FEM_purge_element(theMesh,e1,0); FEM_purge_element(theMesh,e2,0); //get rid of some unnecessary ghost node sends for(int i=0; i<4;i++) { int nodeToUpdate = -1; if(i==0) nodeToUpdate = n1; else if(i==1) nodeToUpdate = n2; else if(i==2) nodeToUpdate = n3; else if(i==3) nodeToUpdate = n4; //if any of the chunks sharing this node sends this as a ghost, then all of them have to //so find out the set of chunks I need to send this as a ghost to //collect info from each of the shared chunks, do a union of all these chunks //send this updated list to everyone. //if anyone needs to add or delete some ghosts, they will int *chkl, numchkl=0; CkVec<int> finalchkl; theMod->fmUtil->findGhostSend(nodeToUpdate, chkl, numchkl); for(int j=0; j<numchkl; j++) { finalchkl.push_back(chkl[j]); } if(numchkl>0) delete[] chkl; const IDXL_Rec *irec=theMesh->node.shared.getRec(nodeToUpdate); int numchunks=0; int *chunks1, *inds1; if(irec) { numchunks = irec->getShared(); chunks1 = new int[numchunks]; inds1 = new int[numchunks]; for(int j=0; j<numchunks; j++) { chunks1[j] = irec->getChk(j); inds1[j] = irec->getIdx(j); } } for(int j=0; j<numchunks; j++) { findgsMsg *fmsg = meshMod[chunks1[j]].findghostsend(index,inds1[j]); if(fmsg->numchks>0) { for(int k=0; k<fmsg->numchks; k++) { bool shouldbeadded = true; for(int l=0; l<finalchkl.size(); l++) { if(fmsg->chunks[k]==finalchkl[l]) { shouldbeadded = false; break; } } if(shouldbeadded) finalchkl.push_back(fmsg->chunks[k]); } } delete fmsg; } int *finall, numfinall=finalchkl.size(); if(numfinall>0) finall = new int[numfinall]; for(int j=0; j<numfinall; j++) finall[j] = finalchkl[j]; finalchkl.free(); theMod->fmUtil->UpdateGhostSend(nodeToUpdate, finall, numfinall); for(int j=0; j<numchunks; j++) { verifyghostsendMsg *vmsg = new(numfinall)verifyghostsendMsg(); vmsg->fromChk = index; vmsg->sharedIdx = inds1[j]; vmsg->numchks = numfinall; for(int k=0; k<numfinall; k++) vmsg->chunks[k] = finall[k]; meshMod[chunks1[j]].updateghostsend(vmsg); } if(numfinall>0) delete[] finall; if(numchunks>0) { delete[] chunks1; delete[] inds1; } } FEM_Modify_UnlockN(theMesh, n5, 0); return n5; }
/** Inverse of edge bisect, this removes a degree 4 vertex n1 and 2 of its adjacent elements. n2 indicates that the two elements removed are adjacent to edge [n1,n2]. This could be performed with edge_contraction, but this is a simpler operation. n3 n3 o o /|\ / \ / | \ / \ / | \ / \ / |n1 \ / \ n5 o----o----o n2 n5 o---------o n2 \ | / \ / \ | / \ / \ | / \ / \|/ \ / o o n4 n4 */ int FEM_Adapt::vertex_remove_help(int e1, int e2, int n1, int n2, int e1_n1, int e1_n2, int e1_n3, int e2_n1, int e2_n2, int e2_n3, int n3, int n4, int n5) { int numNodes = 5; int numElems = 4; int numNodesNew = 4; int numElemsNew = 2; int locknodes[5]; int lockelems[4]; int elemConn[3]; locknodes[0] = n2; locknodes[1] = n3; locknodes[2] = n4; locknodes[3] = n5; locknodes[4] = n1; lockelems[0] = e1; lockelems[1] = e2; lockelems[2] = -1; lockelems[3] = -1; int e3 = theMesh->e2e_getNbr(e1, get_edge_index(e1_n1, e1_n3)); int e4 = -1; lockelems[2] = e3; if (e3 != -1) { if (e2 != -1) { e4 = theMesh->e2e_getNbr(e2, get_edge_index(e2_n1, e2_n3)); lockelems[3] = e4; if(e4 == -1 ) { return 0; } } //FEM_Modify_Lock(theMesh, locknodes, numNodes, lockelems, numElems); int e1chunk=-1, e2chunk=-1, e3chunk=-1, e4chunk=-1; int index = theMod->getIdx(); #ifdef DEBUG_1 CkPrintf("Vertex Remove edge %d->%d on chunk %d\n", n1, n2, theMod->getfmUtil()->getIdx()); #endif e1chunk = FEM_remove_element(theMesh, e1, 0); e3chunk = FEM_remove_element(theMesh, e3, 0); if (e2 != -1) { e2chunk = FEM_remove_element(theMesh, e2, 0); e4chunk = FEM_remove_element(theMesh, e4, 0); } FEM_remove_node(theMesh, n1); // add n2, n5, n3 elemConn[e1_n1] = n2; elemConn[e1_n2] = n3; elemConn[e1_n3] = n5; lockelems[0] = FEM_add_element(theMesh, elemConn, 3, 0, e1chunk); if (e2 != -1) { // add n2, n5, n4 elemConn[e2_n1] = n5; elemConn[e2_n2] = n4; elemConn[e2_n3] = n2; lockelems[1] = FEM_add_element(theMesh, elemConn, 3, 0, e2chunk); } return 1; } return 0; }
/** Perform a Delaunay flip of the edge (n1, n2) returning 1 if successful, 0 if not (likely due to the edge being on a boundary). The convexity of the quadrilateral formed by two faces incident to edge (n1, n2) is assumed. n1 and n2 are assumed to be local to this chunk. An adjacency test is performed on n1 and n2 by searching for an element with edge [n1,n2]. n3 n3 o o / \ /|\ / \ / | \ / \ / | \ / \ / | \ n1 o---------o n2 n1 o | o n2 \ / \ | / \ / \ | / \ / \ | / \ / \|/ o o n4 n4 */ int FEM_Adapt::edge_flip_help(int e1, int e2, int n1, int n2, int e1_n1, int e1_n2, int e1_n3, int n3, int n4, int *locknodes) { int numNodes = 4; int numElems = 2; int lockelems[2]; int elemConn[3]; locknodes[0] = n1; locknodes[1] = n2; locknodes[2] = n3; locknodes[3] = n4; lockelems[0] = e1; lockelems[1] = e2; if(n1 < 0 || n2 < 0) { return -1; } int index = theMod->getIdx(); bool flag = theMod->fmAdaptAlgs->controlQualityF(n1,n2,n3,n4); if(flag) return -1; int e1Topurge = e1; int e2Topurge = e2; #ifdef DEBUG_1 CkPrintf("Flipping edge %d->%d on chunk %d\n", n1, n2, theMod->getfmUtil()->getIdx()); #endif //FEM_Modify_Lock(theMesh, locknodes, numNodes, lockelems, numElems); //if any of the two elements is remote, eat those if(n3 < 0) { e1Topurge = theMod->fmUtil->eatIntoElement(e1); theMesh->e2n_getAll(e1Topurge,elemConn); for(int i=0; i<3; i++) { if(elemConn[i]!=n1 && elemConn[i]!=n2) { n3 = elemConn[i]; } } locknodes[2] = n3; } if(n4 < 0) { e2Topurge = theMod->fmUtil->eatIntoElement(e2); theMesh->e2n_getAll(e2Topurge,elemConn); for(int i=0; i<3; i++) { if(elemConn[i]!=n1 && elemConn[i]!=n2) { n4 = elemConn[i]; } } locknodes[3] = n4; } FEM_remove_element(theMesh,e1Topurge,0,0); FEM_remove_element(theMesh,e2Topurge,0,0); // add n1, n3, n4 elemConn[e1_n1] = n1; elemConn[e1_n2] = n4; elemConn[e1_n3] = n3; lockelems[0] = FEM_add_element(theMesh, elemConn, 3, 0, index); //the attributes should really be interpolated, i.e. on both new elems, //the values should be an average of the previous two elements theMod->fmUtil->copyElemData(0,e1Topurge,lockelems[0]); // add n2, n3, n4 elemConn[e1_n1] = n4; elemConn[e1_n2] = n2; elemConn[e1_n3] = n3; lockelems[1] = FEM_add_element(theMesh, elemConn, 3, 0, index); theMod->fmUtil->copyElemData(0,e1Topurge,lockelems[1]); //both of the new elements copy from one element //purge the two elements FEM_purge_element(theMesh,e1Topurge,0); FEM_purge_element(theMesh,e2Topurge,0); //get rid of some unnecessary ghost node sends for(int i=0; i<4;i++) { int nodeToUpdate = -1; if(i==0) nodeToUpdate = n1; else if(i==1) nodeToUpdate = n2; else if(i==2) nodeToUpdate = n3; else if(i==3) nodeToUpdate = n4; //if any of the chunks sharing this node sends this as a ghost, then all of them have to //so find out the set of chunks I need to send this as a ghost to //collect info from each of the shared chunks, do a union of all these chunks //send this updated list to everyone. //if anyone needs to add or delete some ghosts, they will int *chkl, numchkl=0; CkVec<int> finalchkl; theMod->fmUtil->findGhostSend(nodeToUpdate, chkl, numchkl); for(int j=0; j<numchkl; j++) { finalchkl.push_back(chkl[j]); } if(numchkl>0) delete[] chkl; const IDXL_Rec *irec=theMesh->node.shared.getRec(nodeToUpdate); int numchunks=0; int *chunks1, *inds1; if(irec) { numchunks = irec->getShared(); chunks1 = new int[numchunks]; inds1 = new int[numchunks]; for(int j=0; j<numchunks; j++) { chunks1[j] = irec->getChk(j); inds1[j] = irec->getIdx(j); } } for(int j=0; j<numchunks; j++) { findgsMsg *fmsg = meshMod[chunks1[j]].findghostsend(index,inds1[j]); if(fmsg->numchks>0) { for(int k=0; k<fmsg->numchks; k++) { bool shouldbeadded = true; for(int l=0; l<finalchkl.size(); l++) { if(fmsg->chunks[k]==finalchkl[l]) { shouldbeadded = false; break; } } if(shouldbeadded) finalchkl.push_back(fmsg->chunks[k]); } } delete fmsg; } int *finall, numfinall=finalchkl.size(); if(numfinall>0) finall = new int[numfinall]; for(int j=0; j<numfinall; j++) finall[j] = finalchkl[j]; finalchkl.free(); theMod->fmUtil->UpdateGhostSend(nodeToUpdate, finall, numfinall); for(int j=0; j<numchunks; j++) { verifyghostsendMsg *vmsg = new(numfinall)verifyghostsendMsg(); vmsg->fromChk = index; vmsg->sharedIdx = inds1[j]; vmsg->numchks = numfinall; for(int k=0; k<numfinall; k++) vmsg->chunks[k] = finall[k]; meshMod[chunks1[j]].updateghostsend(vmsg); } if(numfinall>0) delete[] finall; if(numchunks>0) { delete[] chunks1; delete[] inds1; } } //make sure that it always comes here, don't return with unlocking return 1; //return newNode; }