TEST(Mesh, HigherOrderLine1)
{
    UnstructuredMesh* msh = createLineElement(GeoLib::Point(0,0,0), GeoLib::Point(1,0,0), CoordinateSystemType::X);
    std::vector<IElement*> vec_edge;
    createEdgeElements(msh);
    ASSERT_EQ(1u, msh->getNumberOfEdges());
    MeshGenerator::generateHigherOrderUnstrucuredMesh(*msh, 2);

    IElement* e = 0;
    ASSERT_EQ(2u, msh->getNumberOfNodes(1));
    ASSERT_EQ(3u, msh->getNumberOfNodes(2));
    msh->setCurrentOrder(1);
    e = msh->getElement(0);
    ASSERT_EQ(2u, msh->getNumberOfNodes(1));
    ASSERT_EQ(2u, e->getNumberOfNodes());
    msh->setCurrentOrder(2);
    e = msh->getElement(0);
    ASSERT_EQ(3u, msh->getNumberOfNodes(2));
    ASSERT_EQ(3u, e->getNumberOfNodes());

    e->setCurrentOrder(1);
    ASSERT_EQ(2u, e->getNumberOfNodes());
    e->setCurrentOrder(2);
    ASSERT_EQ(3u, e->getNumberOfNodes());

    const GeoLib::Point* p = msh->getNodeCoordinatesRef(2);
    ASSERT_DOUBLE_EQ(0.5, (*p)[0]);
    ASSERT_DOUBLE_EQ(0., (*p)[1]);
    ASSERT_DOUBLE_EQ(0., (*p)[2]);

}
TEST(Mesh, MappingLineXZ2)
{
    UnstructuredMesh* msh = createLineElement(GeoLib::Point(1,0,1), GeoLib::Point(2,0,2), CoordinateSystemType::XZ);
    ElementCoordinatesMappingLocal emap(msh, *msh->getElement(0), msh->getGeometricProperty()->getCoordinateSystem());

    GeoLib::Point* p1 = emap.getNodePoint(0);
    GeoLib::Point* p2 = emap.getNodePoint(1);

    ASSERT_EQ(GeoLib::Point(0,0,0), *p1);
    ASSERT_EQ(GeoLib::Point(sqrt(2.),0,0), *p2);
}
UnstructuredMesh * createLineElement(GeoLib::Point pt1, GeoLib::Point pt2, CoordinateSystemType::type coord_type)
{
    UnstructuredMesh *msh = new UnstructuredMesh(coord_type);
    msh->addNode(pt1);
    msh->addNode(pt2);
    Line *e = new Line();
    e->setNodeID(0,0);
    e->setNodeID(1,1);
    msh->addElement(e);

    return msh;
}
TEST(Mesh, MappingTriYZ1)
{
    UnstructuredMesh* msh = createTriangleElement(GeoLib::Point(0,1,1), GeoLib::Point(0,3,1), GeoLib::Point(0,1,3), CoordinateSystemType::YZ);
    ElementCoordinatesMappingLocal emap(msh, *msh->getElement(0), msh->getGeometricProperty()->getCoordinateSystem());

    GeoLib::Point* p1 = emap.getNodePoint(0);
    GeoLib::Point* p2 = emap.getNodePoint(1);
    GeoLib::Point* p3 = emap.getNodePoint(2);

//    ASSERT_EQ(GeoLib::Point(0,0,0), *p1);
//    ASSERT_EQ(GeoLib::Point(2,0,0), *p2);
//    ASSERT_EQ(GeoLib::Point(0,2,0), *p3);

    ASSERT_EQ(GeoLib::Point(1,1,0), *p1);
    ASSERT_EQ(GeoLib::Point(3,1,0), *p2);
    ASSERT_EQ(GeoLib::Point(1,3,0), *p3);
}
double calculateMeshMinimumEdgeLength(UnstructuredMesh &msh)
{
    std::vector<size_t> vec_edge_nodes;
    double min_edge_len = std::numeric_limits<double>::max();
    const size_t n_ele = msh.getNumberOfElements();
    for (size_t i=0; i<n_ele; i++) {
        MeshLib::IElement* e = msh.getElement(i);
        for (size_t j=0; j<e->getNumberOfEdges(); j++) {
            e->getNodeIDsOfEdges(j, vec_edge_nodes);
            assert (vec_edge_nodes.size() == 2);

            double edge_len = std::sqrt(GeoLib::sqrDist(msh.getNodeCoordinatesRef(vec_edge_nodes[0]), msh.getNodeCoordinatesRef(vec_edge_nodes[1])));
            min_edge_len = std::min(min_edge_len, edge_len);
        }
    }

    return min_edge_len;
}
void calculateMeshGeometricProperties(UnstructuredMesh &msh)
{
    MeshGeometricProperty* geo_prop = msh.getGeometricProperty();
    //double tol = std::numeric_limits<double>::epsilon();

    // coordinate systems
    geo_prop->setCoordinateSystem(getCoordinateSystemFromBoundingBox(geo_prop->getBoundingBox()));

    //
//    GeoLib::Point pt_diff = geo_prop->getBoundingBox().getMaxPoint() - geo_prop->getBoundingBox().getMinPoint();
//    double max_len = std::max(pt_diff[0], pt_diff[1]);
//    max_len = std::max(max_len, pt_diff[2]);
//    double min_edge_len = max_len / msh.getNumberOfNodes();
    double min_edge_len = calculateMeshMinimumEdgeLength(msh);
    geo_prop->setMinEdgeLength(min_edge_len);

    INFO("-> calculate mesh geometric properties");
    INFO("* min. edge length = %f", min_edge_len);

}
  void TriangleWrapper::copy_tri_to_mesh(const triangulateio& triangle_data_input,
					 UnstructuredMesh& mesh_output,
					 const ElemType type)
  {
    // Transfer the information into the LibMesh mesh.
    mesh_output.clear();

    // Make sure the new Mesh will be 2D
    mesh_output.set_mesh_dimension(2);

    // Node information
    for (int i=0, c=0; c<triangle_data_input.numberofpoints; i+=2, ++c)
      {
	// Specify ID when adding point, otherwise, if this is ParallelMesh,
	// it might add points with a non-sequential numbering...
	mesh_output.add_point( Point(triangle_data_input.pointlist[i],
				     triangle_data_input.pointlist[i+1]),
			       /*id=*/c);
      }

    // Element information
    for (int i=0; i<triangle_data_input.numberoftriangles; ++i)
      {
	switch (type)
	  {
	  case TRI3:
	    {
	      Elem* elem = mesh_output.add_elem (new Tri3);

	      for (unsigned int n=0; n<3; ++n)
		elem->set_node(n) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*3 + n]);

	      break;
	    }

	  case TRI6:
	    {
	      Elem* elem = mesh_output.add_elem (new Tri6);

	      // Triangle number TRI6 nodes in a different way to libMesh
	      elem->set_node(0) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 0]);
	      elem->set_node(1) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 1]);
	      elem->set_node(2) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 2]);
	      elem->set_node(3) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 5]);
	      elem->set_node(4) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 3]);
	      elem->set_node(5) = mesh_output.node_ptr(triangle_data_input.trianglelist[i*6 + 4]);

	      break;
	    }

	  default:
	    {
	      libMesh::err << "ERROR: Unrecognized triangular element type." << std::endl;
	      libmesh_error();
	    }
	  }
      }

    // Note: If the input mesh was a parallel one, calling
    // prepare_for_use() now will re-parallelize it by a call to
    // delete_remote_elements()... We do not actually want to
    // reparallelize it here though: the triangulate() function may
    // still do some Mesh smoothing.  The main thing needed (for
    // smoothing) is the neighbor information, so let's just find
    // neighbors...
    //mesh_output.prepare_for_use(/*skip_renumber =*/false);
    mesh_output.find_neighbors();
  }
示例#8
0
void UnstructuredMesh::copy_nodes_and_elements(const UnstructuredMesh & other_mesh,
                                               const bool skip_find_neighbors)
{
  // We're assuming our subclass data needs no copy
  libmesh_assert_equal_to (_n_parts, other_mesh._n_parts);
  libmesh_assert (std::equal(_elem_dims.begin(), _elem_dims.end(), other_mesh._elem_dims.begin()));
  libmesh_assert_equal_to (_is_prepared, other_mesh._is_prepared);

  // We're assuming the other mesh has proper element number ordering,
  // so that we add parents before their children.
#ifdef DEBUG
  MeshTools::libmesh_assert_valid_amr_elem_ids(other_mesh);
#endif

  //Copy in Nodes
  {
    //Preallocate Memory if necessary
    this->reserve_nodes(other_mesh.n_nodes());

    const_node_iterator it = other_mesh.nodes_begin();
    const_node_iterator end = other_mesh.nodes_end();

    for (; it != end; ++it)
      {
        const Node * oldn = *it;

        // Add new nodes in old node Point locations
#ifdef LIBMESH_ENABLE_UNIQUE_ID
        Node *newn =
#endif
          this->add_point(*oldn, oldn->id(), oldn->processor_id());

#ifdef LIBMESH_ENABLE_UNIQUE_ID
        newn->set_unique_id() = oldn->unique_id();
#endif
      }
  }

  //Copy in Elements
  {
    //Preallocate Memory if necessary
    this->reserve_elem(other_mesh.n_elem());

    // Declare a map linking old and new elements, needed to copy the neighbor lists
    std::map<const Elem *, Elem *> old_elems_to_new_elems;

    // Loop over the elements
    MeshBase::const_element_iterator it = other_mesh.elements_begin();
    const MeshBase::const_element_iterator end = other_mesh.elements_end();

    // FIXME: Where do we set element IDs??
    for (; it != end; ++it)
      {
        //Look at the old element
        const Elem * old = *it;
        //Build a new element
        Elem * newparent = old->parent() ?
          this->elem_ptr(old->parent()->id()) : libmesh_nullptr;
        UniquePtr<Elem> ap = Elem::build(old->type(), newparent);
        Elem * el = ap.release();

        el->subdomain_id() = old->subdomain_id();

        for (unsigned int s=0; s != old->n_sides(); ++s)
          if (old->neighbor_ptr(s) == remote_elem)
            el->set_neighbor(s, const_cast<RemoteElem *>(remote_elem));

#ifdef LIBMESH_ENABLE_AMR
        if (old->has_children())
          for (unsigned int c=0; c != old->n_children(); ++c)
            if (old->child_ptr(c) == remote_elem)
              el->add_child(const_cast<RemoteElem *>(remote_elem), c);

        //Create the parent's child pointers if necessary
        if (newparent)
          {
            unsigned int oldc = old->parent()->which_child_am_i(old);
            newparent->add_child(el, oldc);
          }

        // Copy the refinement flags
        el->set_refinement_flag(old->refinement_flag());

        // Use hack_p_level since we may not have sibling elements
        // added yet
        el->hack_p_level(old->p_level());

        el->set_p_refinement_flag(old->p_refinement_flag());
#endif // #ifdef LIBMESH_ENABLE_AMR

        //Assign all the nodes
        for(unsigned int i=0;i<el->n_nodes();i++)
          el->set_node(i) = this->node_ptr(old->node_id(i));

        // And start it off in the same subdomain
        el->processor_id() = old->processor_id();

        // Give it the same ids
        el->set_id(old->id());

#ifdef LIBMESH_ENABLE_UNIQUE_ID
        el->set_unique_id() = old->unique_id();
#endif

        //Hold onto it
        if(!skip_find_neighbors)
          {
            this->add_elem(el);
          }
        else
          {
            Elem * new_el = this->add_elem(el);
            old_elems_to_new_elems[old] = new_el;
          }

        // Add the link between the original element and this copy to the map
        if(skip_find_neighbors)
          old_elems_to_new_elems[old] = el;
      }

    // Loop (again) over the elements to fill in the neighbors
    if(skip_find_neighbors)
      {
        it = other_mesh.elements_begin();
        for (; it != end; ++it)
          {
            Elem * old_elem = *it;
            Elem * new_elem = old_elems_to_new_elems[old_elem];
            for (unsigned int s=0; s != old_elem->n_neighbors(); ++s)
              {
                const Elem * old_neighbor = old_elem->neighbor_ptr(s);
                Elem * new_neighbor = old_elems_to_new_elems[old_neighbor];
                new_elem->set_neighbor(s, new_neighbor);
              }
          }
      }
  }

  //Finally prepare the new Mesh for use.  Keep the same numbering and
  //partitioning but also the same renumbering and partitioning
  //policies as our source mesh.
  this->allow_renumbering(false);
  this->skip_partitioning(true);
  this->prepare_for_use(false, skip_find_neighbors);
  this->allow_renumbering(other_mesh.allow_renumbering());
  this->skip_partitioning(other_mesh.skip_partitioning());
}
示例#9
0
void UnstructuredMesh::create_submesh (UnstructuredMesh & new_mesh,
                                       const_element_iterator & it,
                                       const const_element_iterator & it_end) const
{
  // Just in case the subdomain_mesh already has some information
  // in it, get rid of it.
  new_mesh.clear();

  // If we're not serial, our submesh isn't either.
  // There are no remote elements to delete on an empty mesh, but
  // calling the method to do so marks the mesh as parallel.
  if (!this->is_serial())
    new_mesh.delete_remote_elements();

  // Fail if (*this == new_mesh), we cannot create a submesh inside ourself!
  // This may happen if the user accidently passes the original mesh into
  // this function!  We will check this by making sure we did not just
  // clear ourself.
  libmesh_assert_not_equal_to (this->n_nodes(), 0);
  libmesh_assert_not_equal_to (this->n_elem(), 0);

  // Container to catch boundary IDs handed back by BoundaryInfo
  std::vector<boundary_id_type> bc_ids;

  for (; it != it_end; ++it)
    {
      const Elem * old_elem = *it;

      // Add an equivalent element type to the new_mesh.
      // Copy ids for this element.
      Elem * new_elem = Elem::build(old_elem->type()).release();
      new_elem->set_id() = old_elem->id();
#ifdef LIBMESH_ENABLE_UNIQUE_ID
      new_elem->set_unique_id() = old_elem->unique_id();
#endif
      new_elem->subdomain_id() = old_elem->subdomain_id();
      new_elem->processor_id() = old_elem->processor_id();

      new_mesh.add_elem (new_elem);

      libmesh_assert(new_elem);

      // Loop over the nodes on this element.
      for (unsigned int n=0; n<old_elem->n_nodes(); n++)
        {
          const dof_id_type this_node_id = old_elem->node_id(n);

          // Add this node to the new mesh if it's not there already
          if (!new_mesh.query_node_ptr(this_node_id))
            {
#ifdef LIBMESH_ENABLE_UNIQUE_ID
              Node *newn =
#endif
                new_mesh.add_point (old_elem->point(n),
                                    this_node_id,
                                    old_elem->node_ptr(n)->processor_id());

#ifdef LIBMESH_ENABLE_UNIQUE_ID
              newn->set_unique_id() = old_elem->node_ptr(n)->unique_id();
#endif
            }

          // Define this element's connectivity on the new mesh
          new_elem->set_node(n) = new_mesh.node_ptr(this_node_id);
        }

      // Maybe add boundary conditions for this element
      for (unsigned short s=0; s<old_elem->n_sides(); s++)
        {
          this->get_boundary_info().boundary_ids(old_elem, s, bc_ids);
          new_mesh.get_boundary_info().add_side (new_elem, s, bc_ids);
        }
    } // end loop over elements

  // Prepare the new_mesh for use
  new_mesh.prepare_for_use(/*skip_renumber =*/false);
}