void print_undirected_path_info(undirected_node ** path, int actual_path_length){ printf("Length: %d. ", actual_path_length); int i; int total_cost = 0; for(i = 0; i < actual_path_length; i++){ if(path[i]->track_node1 && path[i]->track_node2){ printf("%s/%s", path[i]->track_node1->name, path[i]->track_node2->name); }else{ printf("train", "dummy"); } if(i != actual_path_length -1){ printf(" -> ", "dummy"); undirected_node * current_node = path[i]; undirected_node * next_node = path[i+1]; int index = get_edge_index(current_node, next_node); assertf(index != -1, "Index not found."); total_cost += current_node->adjacent_nodes.edge[index].micrometers_distance; } } printf(" Cost: %d.\n", total_cost); }
/** Extract elements adjacent to edge [n1,n2] along with element-local node numberings and nodes opposite input edge **/ int FEM_Adapt::findAdjData(int n1, int n2, int *e1, int *e2, int *e1n1, int *e1n2, int *e1n3, int *e2n1, int *e2n2, int *e2n3, int *n3, int *n4) { // Set some default values in case e1 is not there (*e1n1) = (*e1n2) = (*e1n3) = (*n3) = -1; //if n1,n2 is not an edge return if(n1<0 || n2<0) return -1; if(theMesh->node.is_valid(n1)==0 || theMesh->node.is_valid(n2)==0) return -1; if(theMesh->n2n_exists(n1,n2)!=1 || theMesh->n2n_exists(n2,n1)!=1) return -1; (*e1) = theMesh->getElementOnEdge(n1, n2); // assumed to return local element if ((*e1) == -1) { CkPrintf("[%d]Warning: No Element on edge %d->%d\n",theMod->idx,n1,n2); return -1; } (*e1n1) = find_local_node_index((*e1), n1); (*e1n2) = find_local_node_index((*e1), n2); (*e1n3) = 3 - (*e1n1) - (*e1n2); (*n3) = theMesh->e2n_getNode((*e1), (*e1n3)); (*e2) = theMesh->e2e_getNbr((*e1), get_edge_index((*e1n1), (*e1n2))); // Set some default values in case e2 is not there (*e2n1) = (*e2n2) = (*e2n3) = (*n4) = -1; if ((*e2) != -1) { // e2 exists (*e2n1) = find_local_node_index((*e2), n1); (*e2n2) = find_local_node_index((*e2), n2); (*e2n3) = 3 - (*e2n1) - (*e2n2); //if ((*e2) > -1) { // if e2 is a ghost, there is no e2n data (*n4) = theMesh->e2n_getNode((*e2), (*e2n3)); //} } if(*n3 == *n4) { CkPrintf("[%d]Warning: Identical elements %d:(%d,%d,%d) & %d:(%d,%d,%d)\n",theMod->idx,*e1,n1,n2,*n3,*e2,n1,n2,*n4); return -1; } return 1; }
/// Constrained edge functions are constructed by subtracting the linear part (ie., two /// vertex functions) from the constraining edge function and expressing the rest as a /// linear combination of standard edge functions. This function determines the coefficients /// of such linear combination by forming and solving a simple linear system. /// double* Shapeset::calculate_constrained_edge_combination(int order, int part, int ori) { assert((order - ebias) >= 0); assert(part >= 0); int i, j, n; // determine the interval of the edge for (n = 2; n <= part; n <<= 1) part -= n; double n2 = 2.0 / n; double hi = -((double) part * n2 - 1.0); double lo = -((double) (part + 1) * n2 - 1.0); int idx[16]; ori = ori ? 0 : 1; for (i = 0; i <= order; i++) idx[i] = get_edge_index(0, ori, i); // function values at the endpoints (for subtracting of the linear part in H1) double c = 1.0; double f_lo = 0.0, f_hi = 0.0; if (ebias == 2) { f_lo = get_value(0, idx[order], lo, -1.0, 0); f_hi = get_value(0, idx[order], hi, -1.0, 0); } else { // this is for H(curl), where we need to multiply the constrained function // so that its vectors are not shortened and fit the large constraining fn. c = (hi - lo) / 2.0; } // fill the matrix of the linear system n = order + 1 - ebias; int space_type = get_id() / 10; int component = space_type == 2 ? 1 : 0; double** a = new_matrix<double>(n, n); double* b = new double[n]; for (i = 0; i < n; i++) { // chebyshev point int o = (ebias == 0) ? order + 1 : order; double p = cos((i+1) * M_PI / o); double r = (p + 1.0) * 0.5; double s = 1.0 - r; // matrix row for (j = 0; j < n; j++) a[i][j] = get_value(0, idx[j+ebias], p, -1.0, component); // rhs b[i] = c * get_value(0, idx[order], lo*s + hi*r, -1.0, component) - f_lo*s - f_hi*r; } // solve the system double d; int* iperm = new int[n]; ludcmp(a, n, iperm, &d); lubksb(a, n, iperm, b); // cleanup delete [] iperm; delete [] a; return b; }
void Simple_manifold_2:: determine_opposite_halfedges() { // Compute the dual connectivity. Pane_dual_connectivity pdc( _pane, _with_ghost); int nr = _nspe*_pane->size_of_real_elements(); _oeIDs_real_or_str.clear(); _oeIDs_real_or_str.resize( nr, Edge_ID()); int ng = _with_ghost ? _nspe*_pane->size_of_ghost_elements():0; _oeIDs_ghost.clear(); _oeIDs_ghost.resize( ng, Edge_ID()); // Buffer array for holding border edges between real and ghost std::vector<Edge_ID> beIDs_rg; // Determine the neighbor elements from the dual connectivity. Element_node_enumerator ene( _pane, 1); std::vector<int> ies1, ies2; std::vector<int> ies_common; ies_common.reserve(2); // Process real elements of unstructured meshes or structured meshes int nn = _is_str && _with_ghost ? _pane->size_of_elements():_pane->size_of_real_elements(); for ( int j=0; j<nn; ++j, ene.next()) { const int ne = ene.size_of_edges(); COM_assertion( _nspe>=ne); int ij = j*_nspe; for ( int i=0; i<ne; ++i, ++ij) { // Determine the elements that incident on both nodes of the edge pdc.incident_elements( ene[i], ies1); pdc.incident_elements( ene[(i==ne-1)?0:i+1], ies2); ies_common.clear(); std::back_insert_iterator< std::vector<int> > ii(ies_common);; std::set_intersection( ies1.begin(), ies1.end(), ies2.begin(), ies2.end(), ii); COM_assertion( ies_common.size()<=2); int eid=0; for ( std::vector<int>::iterator it_ies = ies_common.begin(); it_ies != ies_common.end(); ++it_ies) if ( *it_ies != ene.id()) { eid = *it_ies; break; } // Determing the local side ID if ( eid) { int node_id = ene[i]; Element_node_enumerator ene_opp( _pane, eid); const int nk=ene_opp.size_of_edges(); for ( int k=0; k<nk; ++k) if ( ene_opp[k] == node_id) { Edge_ID opp = Edge_ID( eid, k?k-1:nk-1); bool isreal_edge = !_with_ghost || !_is_str || is_real_element( ene.id()); bool isghost_opp = _with_ghost && is_ghost_element( eid); if ( isreal_edge || isghost_opp) // ghost elements of structured mesh _oeIDs_real_or_str[ij] = opp; // Insert border edges incident on ghost elements into _beIDs_rg if ( isghost_opp && isreal_edge) { beIDs_rg.push_back( Edge_ID( ene.id(), i)); Edge_ID bid = Edge_ID( beIDs_rg.size(), Edge_ID::BndID); if (_is_str) _oeIDs_real_or_str[ get_edge_index( opp)] = bid; else _oeIDs_ghost[ get_edge_index( opp, _maxsize_real_elmts)] = bid; } break; } COM_assertion( _oeIDs_real_or_str[ij] != Edge_ID()); } // eid else { // Insert border edges of the real part into _beIDs _beIDs.push_back( Edge_ID(ene.id(), i)); _oeIDs_real_or_str[ij] = Edge_ID( _beIDs.size(), Edge_ID::BndID); } } } // Save the number of real borders edges. _size_real_borders = _beIDs.size(); _size_rg_borders = beIDs_rg.size(); // Update the rg_border IDs for ( int i=0; i<_size_rg_borders; ++i) { Edge_ID gid = _oeIDs_real_or_str[get_edge_index(beIDs_rg[i])]; Edge_ID *bid; if ( _is_str) bid = &_oeIDs_real_or_str[ get_edge_index( gid)]; else bid = &_oeIDs_ghost[ get_edge_index( gid, _maxsize_real_elmts)]; COM_assertion( bid->eid() == i+1); *bid = Edge_ID( bid->eid()+_size_real_borders, Edge_ID::BndID); } // Merge _beIDs and beIDs_rg together _beIDs.insert( _beIDs.end(), beIDs_rg.begin(), beIDs_rg.end()); beIDs_rg.clear(); // Process ghost elements nn = _is_str || !_with_ghost ? 0 : _pane->size_of_ghost_elements(); if ( nn) ene = Element_node_enumerator( _pane, _maxsize_real_elmts+1); for ( int j=0; j<nn; ++j, ene.next()) { const int ne = ene.size_of_edges(); COM_assertion( _nspe>=ne); int ij = j*_nspe; for ( int i=0; i<ne; ++i, ++ij) { // Determine the elements that incident on both nodes of the edge pdc.incident_elements( ene[i], ies1); pdc.incident_elements( ene[(i==ne-1)?0:i+1], ies2); ies_common.clear(); std::back_insert_iterator< std::vector<int> > ii(ies_common);; std::set_intersection( ies1.begin(), ies1.end(), ies2.begin(), ies2.end(), ii); COM_assertion( ies_common.size()<=2); int eid=0; for ( std::vector<int>::iterator it_ies = ies_common.begin(); it_ies != ies_common.end(); ++it_ies) if ( *it_ies != ene.id()) { eid = *it_ies; break; } // Determing the local side ID if ( eid) { if ( is_real_element( eid)) continue; int node_id = ene[i]; Element_node_enumerator ene_opp( _pane, eid); const int nk=ene_opp.size_of_edges(); for ( int k=0; k<nk; ++k) if ( ene_opp[k] == node_id) { _oeIDs_ghost[ij] = Edge_ID( eid, k?k-1:nk-1); break; } COM_assertion( _oeIDs_ghost[ij] != Edge_ID()); } else { // Insert border edges of the ghost part of the pane into _beIDs _beIDs.push_back( Edge_ID(ene.id(), i)); _oeIDs_ghost[ij] = Edge_ID( _beIDs.size(), Edge_ID::BndID); } } } _size_ghost_borders = _beIDs.size() - _size_real_borders - _size_rg_borders; }
int FEM_Adapt::vertex_split(int n, int n1, int n2, int e1, int e3) { int n_e1 = find_local_node_index(e1, n); int n1_e1 = find_local_node_index(e1, n1); int e2 = theMesh->e2e_getNbr(e1, get_edge_index(n_e1, n1_e1)); int n_e3 = find_local_node_index(e3, n); int n2_e3 = find_local_node_index(e3, n2); int e4 = theMesh->e2e_getNbr(e3, get_edge_index(n_e3, n2_e3)); if (!check_orientation(e1, e3, n, n1, n2)) { int tmp = e3; e3 = e4; e4 = tmp; n_e3 = find_local_node_index(e3, n); n2_e3 = find_local_node_index(e3, n2); } int np = newNode(); int e5 = newElement(); int e6 = newElement(); int nnCount=0, neCount=0; int np_nodes[50], np_elems[50]; // I certainly hope the mesh is not this bad adj_traverse(n, n1, n2, e2, e4, &nnCount, &neCount, np_nodes, np_elems); // Element-to-node updates int nl[3]; if ((n_e1 < n1_e1) || ((n_e1 == 2) && (n1_e1 == 0))) { nl[0] = n1; nl[1] = n; nl[2] = np; theMesh->e2n_setAll(e5, nl); nl[0] = e1; nl[1] = e6; nl[2] = e2; theMesh->e2e_setAll(e5, nl); } else { nl[0] = n; nl[1] = n1; nl[2] = np; theMesh->e2n_setAll(e5, nl); nl[0] = e1; nl[1] = e2; nl[2] = e6; theMesh->e2e_setAll(e5, nl); } if ((n_e3 < n2_e3) || ((n_e3 == 2) && (n2_e3 == 0))) { nl[0] = n2; nl[1] = n; nl[2] = np; theMesh->e2n_setAll(e6, nl); nl[0] = e3; nl[1] = e5; nl[2] = e4; theMesh->e2e_setAll(e6, nl); } else { nl[0] = n; nl[1] = n2; nl[2] = np; theMesh->e2n_setAll(e6, nl); nl[0] = e3; nl[1] = e4; nl[2] = e5; theMesh->e2e_setAll(e6, nl); } theMesh->e2n_replace(e2, n, np); theMesh->e2n_replace(e4, n, np); // Element-to-element updates theMesh->e2e_replace(e1, e2, e5); theMesh->e2e_replace(e2, e1, e5); theMesh->e2e_replace(e3, e4, e6); theMesh->e2e_replace(e4, e3, e6); // Node-to-node updates int i; for (i=0; i<nnCount; i++) { printf("np_nodes[%d] = %d\n", i, np_nodes[i]); theMesh->n2n_remove(n, np_nodes[i]); theMesh->n2n_remove(np_nodes[i], n); theMesh->n2n_add(np, np_nodes[i]); theMesh->n2n_add(np_nodes[i], np); } theMesh->n2n_add(n, np); theMesh->n2n_add(np, n); theMesh->n2n_add(n, n1); theMesh->n2n_add(n1, n); theMesh->n2n_add(n, n2); theMesh->n2n_add(n2, n); // Node-to-element updates for (i=0; i<neCount; i++) { theMesh->n2e_remove(n, np_elems[i]); theMesh->e2n_replace(np_elems[i], n, np); theMesh->n2e_add(np, np_elems[i]); } theMesh->n2e_add(n, e5); theMesh->n2e_add(n, e6); theMesh->n2e_add(n1, e5); theMesh->n2e_add(n2, e6); theMesh->n2e_add(np, e5); theMesh->n2e_add(np, e6); return np; }
int FEM_Adapt::edge_contraction_help(int e1, int e2, int n1, int n2, int e1_n1, int e1_n2) { int e1_n3 = 3 - e1_n1 - e1_n2; int mod_edge1 = get_edge_index(e1_n1, e1_n3); int e1nbr1 = theMesh->e2e_getNbr(e1, mod_edge1); int mod_edge2 = get_edge_index(e1_n2, e1_n3); int e1nbr2 = theMesh->e2e_getNbr(e1, mod_edge2); int n3 = theMesh->e2n_getNode(e1, e1_n3); int e2_n1; int e2_n2; int e2_n3; int mod_edge3; int e2nbr1; int mod_edge4; int e2nbr2; int n4; if (e2 > -1) { e2_n1 = find_local_node_index(e2, n1); e2_n2 = find_local_node_index(e2, n2); e2_n3 = 3 - e2_n1 - e2_n2; mod_edge3 = get_edge_index(e2_n1, e2_n3); e2nbr1 = theMesh->e2e_getNbr(e2, mod_edge3); mod_edge4 = get_edge_index(e2_n2, e2_n3); e2nbr2 = theMesh->e2e_getNbr(e2, mod_edge4); n4 = theMesh->e2n_getNode(e2, e2_n3); } int *n2_nbrNodes, *n2_nbrElems; int nnsize, nesize; theMesh->n2n_getAll(n2, &n2_nbrNodes, &nnsize); theMesh->n2e_getAll(n2, &n2_nbrElems, &nesize); // Element-to-node updates for (int i=0; i<nesize; i++) { theMesh->e2n_replace(n2_nbrElems[i], n2, n1); theMesh->n2e_add(n1, n2_nbrElems[i]); } theMesh->n2e_remove(n1, e1); // assume duplicated by loop add above theMesh->n2e_remove(n1, e2); // assume duplicated by loop add above // Element-to-element updates theMesh->e2e_replace(e1nbr1, e1, e1nbr2); theMesh->e2e_replace(e1nbr2, e1, e1nbr1); theMesh->e2e_replace(e2nbr1, e2, e2nbr2); theMesh->e2e_replace(e2nbr2, e2, e2nbr1); // Node-to-node updates for (int i=0; i<nnsize; i++) { if (n2_nbrNodes[i] != n1) { theMesh->n2n_remove(n2_nbrNodes[i], n1); theMesh->n2n_replace(n2_nbrNodes[i], n2, n1); theMesh->n2n_remove(n1, n2_nbrNodes[i]); theMesh->n2n_add(n1, n2_nbrNodes[i]); } } theMesh->n2n_remove(n1, n2); theMesh->n2n_remove(n3, n2); theMesh->n2n_remove(n4, n2); // Node-to-element updates theMesh->n2e_remove(n1, e1); theMesh->n2e_remove(n1, e2); theMesh->n2e_remove(n3, e1); theMesh->n2e_remove(n4, e2); deleteNode(n2); deleteElement(e1); deleteElement(e2); return 1; }
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; }
/** 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; }