Esempio n. 1
0
  void ElemCutter::find_intersection_points(const Elem &elem,
					    const std::vector<Real> &vertex_distance_func)
  {
    _intersection_pts.clear();

    for (unsigned int e=0; e<elem.n_edges(); e++)
      {
	AutoPtr<Elem> edge (elem.build_edge(e));

	// find the element nodes el0, el1 that map
	unsigned int
	  el0 = elem.get_node_index(edge->get_node(0)),
	  el1 = elem.get_node_index(edge->get_node(1));

	libmesh_assert (elem.is_vertex(el0));
	libmesh_assert (elem.is_vertex(el1));
	libmesh_assert_less (el0, vertex_distance_func.size());
	libmesh_assert_less (el1, vertex_distance_func.size());

	const Real
	  d0 = vertex_distance_func[el0],
	  d1 = vertex_distance_func[el1];

	// if this egde has a 0 crossing
	if (d0*d1 < 0.)
	  {
	    libmesh_assert_not_equal_to (d0, d1);

	    // then find d_star in [0,1], the
	    // distance from el0 to el1 where the 0 lives.
	    const Real d_star = d0 / (d0 - d1);


	    // Prevent adding nodes trivially close to existing
	    // nodes.
	    const Real endpoint_tol = 0.01;

	    if ( (d_star > endpoint_tol) &&
		 (d_star < (1.-endpoint_tol)) )
	      {
		const Point x_star = (edge->point(0)*(1.-d_star) +
				      edge->point(1)*d_star);

		std::cout << "adding cut point (d_star, x_star) = "
			  << d_star << " , " << x_star << std::endl;

		_intersection_pts.push_back (x_star);
	      }
	  }
      }
  }
//-----------------------------------------------------------------
// Mesh refinement methods
bool MeshRefinement::limit_level_mismatch_at_edge (const unsigned int max_mismatch)
{
  // This function must be run on all processors at once
  parallel_only();

  bool flags_changed = false;


  // Maps holding the maximum element level that touches an edge
  std::map<std::pair<unsigned int, unsigned int>, unsigned char>
    max_level_at_edge;
  std::map<std::pair<unsigned int, unsigned int>, unsigned char>
    max_p_level_at_edge;

  // Loop over all the active elements & fill the maps
  {
    MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = _mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
	const Elem* elem = *elem_it;
	const unsigned char elem_level =
	  elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0);
	const unsigned char elem_p_level =
	  elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0);

	// Set the max_level at each edge
	for (unsigned int n=0; n<elem->n_edges(); n++)
	  {
            AutoPtr<Elem> edge = elem->build_edge(n);
            unsigned int childnode0 = edge->node(0);
            unsigned int childnode1 = edge->node(1);
            if (childnode1 < childnode0)
              std::swap(childnode0, childnode1);

	    for (const Elem *p = elem; p != NULL; p = p->parent())
	      {
                AutoPtr<Elem> pedge = p->build_edge(n);
		unsigned int node0 = pedge->node(0);
		unsigned int node1 = pedge->node(1);

                if (node1 < node0)
                  std::swap(node0, node1);

		// If elem does not share this edge with its ancestor
		// p, refinement levels of elements sharing p's edge
		// are not restricted by refinement levels of elem.
		// Furthermore, elem will not share this edge with any
		// of p's ancestors, so we can safely break out of the
		// for loop early.
		if (node0 != childnode0 && node1 != childnode1)
		  break;

                childnode0 = node0;
                childnode1 = node1;

                std::pair<unsigned int, unsigned int> edge_key =
                  std::make_pair(node0, node1);

                if (max_level_at_edge.find(edge_key) ==
                    max_level_at_edge.end())
                  {
                    max_level_at_edge[edge_key] = elem_level;
	            max_p_level_at_edge[edge_key] = elem_p_level;
                  }
                else
                  {
	            max_level_at_edge[edge_key] =
	              std::max (max_level_at_edge[edge_key], elem_level);
	            max_p_level_at_edge[edge_key] =
	              std::max (max_p_level_at_edge[edge_key], elem_p_level);
                  }
              }
	  }
      }
  }


  // Now loop over the active elements and flag the elements
  // who violate the requested level mismatch
  {
    MeshBase::element_iterator       elem_it  = _mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = _mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
	Elem* elem = *elem_it;
	const unsigned int elem_level = elem->level();
	const unsigned int elem_p_level = elem->p_level();

	// Skip the element if it is already fully flagged
	if (elem->refinement_flag() == Elem::REFINE &&
            elem->p_refinement_flag() == Elem::REFINE)
	  continue;

	// Loop over the nodes, check for possible mismatch
	for (unsigned int n=0; n<elem->n_edges(); n++)
	  {
            AutoPtr<Elem> edge = elem->build_edge(n);
            unsigned int node0 = edge->node(0);
            unsigned int node1 = edge->node(1);
            if (node1 < node0)
              std::swap(node0, node1);

            std::pair<unsigned int, unsigned int> edge_key =
              std::make_pair(node0, node1);

	    // Flag the element for refinement if it violates
	    // the requested level mismatch
	    if ( (elem_level + max_mismatch) < max_level_at_edge[edge_key]
                 && elem->refinement_flag() != Elem::REFINE)
	      {
		elem->set_refinement_flag (Elem::REFINE);
		flags_changed = true;
	      }
	    if ( (elem_p_level + max_mismatch) < max_p_level_at_edge[edge_key]
                 && elem->p_refinement_flag() != Elem::REFINE)
	      {
		elem->set_p_refinement_flag (Elem::REFINE);
		flags_changed = true;
	      }
	  }
      }
  }

  // If flags changed on any processor then they changed globally
  CommWorld.max(flags_changed);

  return flags_changed;
}