コード例 #1
0
ファイル: undirected_nodes.c プロジェクト: RobertElder/CS452
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);
}
コード例 #2
0
ファイル: adapt.C プロジェクト: davidheryanto/sc14
/** 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;
}
コード例 #3
0
ファイル: shapeset.cpp プロジェクト: Richardma/hermes2d
/// 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;
}
コード例 #4
0
ファイル: Simple_manifold_2.C プロジェクト: xyuan/IMPACT
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;
}
コード例 #5
0
ファイル: fem_adapt.C プロジェクト: davidheryanto/sc14
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;
}
コード例 #6
0
ファイル: fem_adapt.C プロジェクト: davidheryanto/sc14
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;
}
コード例 #7
0
ファイル: adapt.C プロジェクト: davidheryanto/sc14
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;
}
コード例 #8
0
ファイル: adapt.C プロジェクト: davidheryanto/sc14
/** 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;
}