Beispiel #1
0
UniquePtr<Elem> Tri::side (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_sides());

  Elem* edge = new Edge2;

  switch (i)
    {
    case 0:
      {
        edge->set_node(0) = this->get_node(0);
        edge->set_node(1) = this->get_node(1);
        break;
      }
    case 1:
      {
        edge->set_node(0) = this->get_node(1);
        edge->set_node(1) = this->get_node(2);
        break;
      }
    case 2:
      {
        edge->set_node(0) = this->get_node(2);
        edge->set_node(1) = this->get_node(0);
        break;
      }
    default:
      libmesh_error_msg("Invalid side i = " << i);
    }

  return UniquePtr<Elem>(edge);
}
Beispiel #2
0
AutoPtr<Elem> Quad::side (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_sides());

  Elem* edge = new Edge2;

  switch (i)
    {
    case 0:
      {
	edge->set_node(0) = this->get_node(0);
	edge->set_node(1) = this->get_node(1);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    case 1:
      {
	edge->set_node(0) = this->get_node(1);
	edge->set_node(1) = this->get_node(2);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    case 2:
      {
	edge->set_node(0) = this->get_node(2);
	edge->set_node(1) = this->get_node(3);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    case 3:
      {
	edge->set_node(0) = this->get_node(3);
	edge->set_node(1) = this->get_node(0);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    default:
      {
	libmesh_error();
      }
    }


  // We will never get here...  Look at the code above.
  libmesh_error();
  AutoPtr<Elem> ap_edge(edge);
  return ap_edge;
}
UniquePtr<Elem> InfQuad::side (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_sides());

  // To be returned wrapped in an UniquePtr
  Elem* edge = NULL;

  switch (i)
    {
    case 0: // base face
      {
        edge = new Edge2;
        break;
      }

    case 1: // adjacent to another infinite element
    case 2: // adjacent to another infinite element
      {
        edge = new InfEdge2;
        break;
      }

    default:
      libmesh_error_msg("Invalid side i = " << i);
    }

  // Set the nodes
  for (unsigned n=0; n<edge->n_nodes(); ++n)
    edge->set_node(n) = this->get_node(InfQuad4::side_nodes_map[i][n]);

  return UniquePtr<Elem>(edge);
}
Beispiel #4
0
UniquePtr<Elem> Pyramid::side_ptr (const unsigned int i)
{
  libmesh_assert_less (i, this->n_sides());

  // To be returned wrapped in a UniquePtr
  Elem * face = libmesh_nullptr;

  // Set up the type of element
  switch (i)
    {
    case 0: // triangular face 1
    case 1: // triangular face 2
    case 2: // triangular face 3
    case 3: // triangular face 4
      {
        face = new Tri3;
        break;
      }
    case 4:  // the quad face at z=0
      {
        face = new Quad4;
        break;
      }
    default:
      libmesh_error_msg("Invalid side i = " << i);
    }

  // Set the nodes
  for (unsigned n=0; n<face->n_nodes(); ++n)
    face->set_node(n) = this->node_ptr(Pyramid5::side_nodes_map[i][n]);

  return UniquePtr<Elem>(face);
}
Beispiel #5
0
UniquePtr<Elem> Prism::side (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_sides());

  Elem * face = libmesh_nullptr;

  // Set up the type of element
  switch (i)
    {
    case 0: // the triangular face at z=0
    case 4: // the triangular face at z=1
      {
        face = new Tri3;
        break;
      }
    case 1: // the quad face at y=0
    case 2: // the other quad face
    case 3: // the quad face at x=0
      {
        face = new Quad4;
        break;
      }
    default:
      libmesh_error_msg("Invalid side i = " << i);
    }

  // Set the nodes
  for (unsigned n=0; n<face->n_nodes(); ++n)
    face->set_node(n) = this->node_ptr(Prism6::side_nodes_map[i][n]);

  return UniquePtr<Elem>(face);
}
Beispiel #6
0
UniquePtr<Elem> Pyramid5::build_side_ptr (const unsigned int i,
                                          bool proxy)
{
  libmesh_assert_less (i, this->n_sides());

  if (proxy)
    {
      switch (i)
        {
        case 0:
        case 1:
        case 2:
        case 3:
          return UniquePtr<Elem>(new Side<Tri3,Pyramid5>(this,i));

        case 4:
          return UniquePtr<Elem>(new Side<Quad4,Pyramid5>(this,i));

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }
    }

  else
    {
      // Create NULL pointer to be initialized, returned later.
      Elem * face = libmesh_nullptr;

      switch (i)
        {
        case 0: // triangular face 1
        case 1: // triangular face 2
        case 2: // triangular face 3
        case 3: // triangular face 4
          {
            face = new Tri3;
            break;
          }
        case 4: // the quad face at z=0
          {
            face = new Quad4;
            break;
          }
        default:
          libmesh_error_msg("Invalid side i = " << i);
        }

      face->subdomain_id() = this->subdomain_id();

      // Set the nodes
      for (unsigned n=0; n<face->n_nodes(); ++n)
        face->set_node(n) = this->node_ptr(Pyramid5::side_nodes_map[i][n]);

      return UniquePtr<Elem>(face);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}
Beispiel #7
0
UniquePtr<Elem> Edge::build_side (const unsigned int i, bool) const
{
  libmesh_assert_less (i, 2);
  const Elem* the_parent = this;
  Elem *nodeelem = new NodeElem(const_cast<Elem*>(the_parent));
  nodeelem->set_node(0) = this->get_node(i);
  return UniquePtr<Elem>(nodeelem);
}
  void build_mesh()
  {
    _mesh = new SerialMesh(*TestCommWorld);

    /*
      (0,1)           (1,1)
        x---------------x
        |               |
        |               |
        |               |
        |               |
        |               |
        x---------------x
       (0,0)           (1,0)
        |               |
        |               |
        |               |
        |               |
        x---------------x
       (0,-1)          (1,-1)
     */

    _mesh->set_mesh_dimension(2);

    _mesh->add_point( Point(0.0,-1.0), 4 );
    _mesh->add_point( Point(1.0,-1.0), 5 );
    _mesh->add_point( Point(1.0, 0.0), 1 );
    _mesh->add_point( Point(1.0, 1.0), 2 );
    _mesh->add_point( Point(0.0, 1.0), 3 );
    _mesh->add_point( Point(0.0, 0.0), 0 );

    {
      Elem* elem_top = _mesh->add_elem( new Quad4 );
      elem_top->set_node(0) = _mesh->node_ptr(0);
      elem_top->set_node(1) = _mesh->node_ptr(1);
      elem_top->set_node(2) = _mesh->node_ptr(2);
      elem_top->set_node(3) = _mesh->node_ptr(3);

      Elem* elem_bottom = _mesh->add_elem( new Quad4 );
      elem_bottom->set_node(0) = _mesh->node_ptr(4);
      elem_bottom->set_node(1) = _mesh->node_ptr(5);
      elem_bottom->set_node(2) = _mesh->node_ptr(1);
      elem_bottom->set_node(3) = _mesh->node_ptr(0);

      Elem* edge = _mesh->add_elem( new Edge2 );
      edge->set_node(0) = _mesh->node_ptr(0);
      edge->set_node(1) = _mesh->node_ptr(1);

      // 2D elements will have subdomain id 0, this one will have 1
      edge->subdomain_id() = 1;
    }

    // libMesh will renumber, but we numbered according to its scheme
    // anyway. We do this because when we call uniformly_refine subsequenly,
    // it's going use skip_renumber=false.
    _mesh->prepare_for_use(false /*skip_renumber*/);
  }
Beispiel #9
0
UniquePtr<Elem> Tri3::build_side (const unsigned int i,
                                  bool proxy) const
{
  libmesh_assert_less (i, this->n_sides());

  if (proxy)
    return UniquePtr<Elem>(new Side<Edge2,Tri3>(this,i));

  else
    {
      Elem* edge = new Edge2;
      edge->subdomain_id() = this->subdomain_id();

      switch (i)
        {
        case 0:
          {
            edge->set_node(0) = this->get_node(0);
            edge->set_node(1) = this->get_node(1);
            break;
          }
        case 1:
          {
            edge->set_node(0) = this->get_node(1);
            edge->set_node(1) = this->get_node(2);
            break;
          }
        case 2:
          {
            edge->set_node(0) = this->get_node(2);
            edge->set_node(1) = this->get_node(0);
            break;
          }
        default:
          libmesh_error_msg("Invalid side i = " << i);
        }

      return UniquePtr<Elem>(edge);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}
Beispiel #10
0
UniquePtr<Elem> Hex::side (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_sides());

  Elem * face = new Quad4;

  for (unsigned n=0; n<face->n_nodes(); ++n)
    face->set_node(n) = this->get_node(Hex8::side_nodes_map[i][n]);

  return UniquePtr<Elem>(face);
}
Beispiel #11
0
UniquePtr<Elem> Tet::side_ptr (const unsigned int i)
{
  libmesh_assert_less (i, this->n_sides());

  Elem * face = new Tri3;

  for (unsigned n=0; n<face->n_nodes(); ++n)
    face->set_node(n) = this->node_ptr(Tet4::side_nodes_map[i][n]);

  return UniquePtr<Elem>(face);
}
Beispiel #12
0
UniquePtr<Elem> Tri::side (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_sides());

  Elem* edge = new Edge2;

  for (unsigned n=0; n<edge->n_nodes(); ++n)
    edge->set_node(n) = this->get_node(Tri3::side_nodes_map[i][n]);

  return UniquePtr<Elem>(edge);
}
Beispiel #13
0
UniquePtr<Elem> InfHex::side (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_sides());

  // To be returned wrapped in a UniquePtr
  Elem * face = libmesh_nullptr;

  // Think of a unit cube: (-1,1) x (-1,1) x (-1,1),
  // with (in general) the normals pointing outwards
  switch (i)
    {
      // the face at z = -1
      // the base, where the infinite element couples to conventional
      // elements
    case 0:
      {
        // Oops, here we are, claiming the normal of the face
        // elements point outwards -- and this is the exception:
        // For the side built from the base face,
        // the normal is pointing _into_ the element!
        // Why is that? - In agreement with build_side(),
        // which in turn _has_ to build the face in this
        // way as to enable the cool way \p InfFE re-uses \p FE.
        face = new Quad4;
        break;
      }

      // These faces connect to other infinite elements.
    case 1: // the face at y = -1
    case 2: // the face at x = 1
    case 3: // the face at y = 1
    case 4: // the face at x = -1
      {
        face = new InfQuad4;
        break;
      }

    default:
      libmesh_error_msg("Invalid side i = " << i);
    }

  // Set the nodes
  for (unsigned n=0; n<face->n_nodes(); ++n)
    face->set_node(n) = this->node_ptr(InfHex8::side_nodes_map[i][n]);

  return UniquePtr<Elem>(face);
}
Beispiel #14
0
UniquePtr<Elem> Tet::side (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_sides());

  Elem* face = new Tri3;

  switch (i)
    {
    case 0:
      {
        face->set_node(0) = this->get_node(0);
        face->set_node(1) = this->get_node(2);
        face->set_node(2) = this->get_node(1);
        break;
      }
    case 1:
      {
        face->set_node(0) = this->get_node(0);
        face->set_node(1) = this->get_node(1);
        face->set_node(2) = this->get_node(3);
        break;
      }
    case 2:
      {
        face->set_node(0) = this->get_node(1);
        face->set_node(1) = this->get_node(2);
        face->set_node(2) = this->get_node(3);
        break;
      }
    case 3:
      {
        face->set_node(0) = this->get_node(2);
        face->set_node(1) = this->get_node(0);
        face->set_node(2) = this->get_node(3);
        break;
      }
    default:
      libmesh_error_msg("Invalid side i = " << i);
    }

  return UniquePtr<Elem>(face);
}
  void testPostInitAddElem()
  {
    ReplicatedMesh mesh(*TestCommWorld);

    EquationSystems es(mesh);
    System &sys = es.add_system<System> ("SimpleSystem");
    sys.add_variable("u", FIRST);

    MeshTools::Generation::build_line (mesh, 10, 0., 1., EDGE2);
    es.init();

    Elem* e = Elem::build(EDGE2).release();
    e->set_id(mesh.max_elem_id());
    e->processor_id() = 0;
    e->set_node(0) = mesh.node_ptr(2);
    e->set_node(1) = mesh.node_ptr(8);
    mesh.add_elem(e);
    mesh.prepare_for_use();

    es.reinit();
  }
Beispiel #16
0
UniquePtr<Elem> Tet10::build_side (const unsigned int i,
                                   bool proxy) const
{
  libmesh_assert_less (i, this->n_sides());

  if (proxy)
    return UniquePtr<Elem>(new Side<Tri6,Tet10>(this,i));

  else
    {
      Elem * face = new Tri6;
      face->subdomain_id() = this->subdomain_id();

      for (unsigned n=0; n<face->n_nodes(); ++n)
        face->set_node(n) = this->get_node(Tet10::side_nodes_map[i][n]);

      return UniquePtr<Elem>(face);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}
Beispiel #17
0
UniquePtr<Elem> Tri6::build_side (const unsigned int i,
                                  bool proxy) const
{
  libmesh_assert_less (i, this->n_sides());

  if (proxy)
    return UniquePtr<Elem>(new Side<Edge3,Tri6>(this,i));

  else
    {
      Elem* edge = new Edge3;
      edge->subdomain_id() = this->subdomain_id();

      // Set the nodes
      for (unsigned n=0; n<edge->n_nodes(); ++n)
        edge->set_node(n) = this->get_node(Tri6::side_nodes_map[i][n]);

      return UniquePtr<Elem>(edge);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}
Beispiel #18
0
void OFFIO::read_stream(std::istream& in)
{
  // This is a serial-only process for now;
  // the Mesh should be read on processor 0 and
  // broadcast later
  libmesh_assert_equal_to (this->mesh().processor_id(), 0);

  // Get a reference to the mesh
  MeshBase& the_mesh = MeshInput<MeshBase>::mesh();

  // Clear any existing mesh data
  the_mesh.clear();

  // Check the input buffer
  libmesh_assert (in.good());

  unsigned int nn, ne, nf;

  std::string label;

  // Read the first string.  It should say "OFF"
  in >> label;

  libmesh_assert_equal_to (label, "OFF");

  // read the number of nodes, faces, and edges
  in >> nn >> nf >> ne;


  Real x=0., y=0., z=0.;

  // Read the nodes
  for (unsigned int n=0; n<nn; n++)
    {
      libmesh_assert (in.good());

      in >> x
	 >> y
	 >> z;

      the_mesh.add_point ( Point(x,y,z), n );
    }

  unsigned int nv, nid;

  // Read the elements
  for (unsigned int e=0; e<nf; e++)
    {
      libmesh_assert (in.good());

      // The number of vertices in the element
      in >> nv;

      libmesh_assert(nv == 2 || nv == 3);
      if (e == 0)
      {
        the_mesh.set_mesh_dimension(nv-1);
        if (nv == 3)
        {
#if LIBMESH_DIM < 2
          libMesh::err << "Cannot open dimension 2 mesh file when configured without 2D support." <<
                          std::endl;
          libmesh_error();
#endif
        }
      }

      Elem* elem;
      switch (nv)
      {
        case 2: elem = new Edge2; break;
        case 3: elem = new Tri3 ; break;
        default: libmesh_error();
      }

      elem->set_id(e);
      the_mesh.add_elem (elem);

      for (unsigned int i=0; i<nv; i++)
      {
        in >> nid;
        elem->set_node(i) = the_mesh.node_ptr(nid);
      }
    }
}
std::unique_ptr<MeshBase>
SpiralAnnularMeshGenerator::generate()
{
  std::unique_ptr<ReplicatedMesh> mesh = libmesh_make_unique<ReplicatedMesh>(comm(), 2);

  {
    // Compute the radial bias given:
    // .) the inner radius
    // .) the outer radius
    // .) the initial_delta_r
    // .) the desired number of intervals
    // Note: the exponent n used in the formula is one less than the
    // number of rings the user requests.
    Real alpha = 1.1;
    int n = _num_rings - 1;

    // lambda used to compute the residual and Jacobian for the Newton iterations.
    // We capture parameters which don't need to change from the current scope at
    // the time this lambda is declared. The values are not updated later, so we
    // can't use this for e.g. f, df, and alpha.
    auto newton = [this, n](Real & f, Real & df, const Real & alpha) {
      f = (1. - std::pow(alpha, n + 1)) / (1. - alpha) -
          (_outer_radius - _inner_radius) / _initial_delta_r;
      df = (-(n + 1) * (1 - alpha) * std::pow(alpha, n) + (1. - std::pow(alpha, n + 1))) /
           (1. - alpha) / (1. - alpha);
    };

    Real f, df;
    int num_iter = 1;
    newton(f, df, alpha);

    while (std::abs(f) > 1.e-9 && num_iter <= 25)
    {
      // Compute and apply update.
      Real dx = -f / df;
      alpha += dx;
      newton(f, df, alpha);
      num_iter++;
    }

    // In case the Newton iteration fails to converge.
    if (num_iter > 25)
      mooseError("Newton iteration failed to converge (more than 25 iterations).");

    // Set radial basis to the value of alpha that we computed with Newton.
    _radial_bias = alpha;
  }

  // The number of rings specified by the user does not include the ring at
  // the surface of the cylinder itself, so we increment it by one now.
  _num_rings += 1;

  // Data structure that holds pointers to the Nodes of each ring.
  std::vector<std::vector<Node *>> ring_nodes(_num_rings);

  // Initialize radius and delta_r variables.
  Real radius = _inner_radius;
  Real delta_r = _initial_delta_r;

  // Node id counter.
  unsigned int current_node_id = 0;

  for (std::size_t r = 0; r < _num_rings; ++r)
  {
    ring_nodes[r].resize(_nodes_per_ring);

    // Add nodes starting from either theta=0 or theta=pi/nodes_per_ring
    Real theta = r % 2 == 0 ? 0 : (libMesh::pi / _nodes_per_ring);
    for (std::size_t n = 0; n < _nodes_per_ring; ++n)
    {
      ring_nodes[r][n] = mesh->add_point(Point(radius * std::cos(theta), radius * std::sin(theta)),
                                         current_node_id++);
      // Update angle
      theta += 2 * libMesh::pi / _nodes_per_ring;
    }

    // Go to next ring
    radius += delta_r;
    delta_r *= _radial_bias;
  }

  // Add elements
  for (std::size_t r = 0; r < _num_rings - 1; ++r)
  {
    // even -> odd ring
    if (r % 2 == 0)
    {
      // Inner ring (n, n*, n+1)
      // Starred indices refer to nodes on the "outer" ring of this pair.
      for (std::size_t n = 0; n < _nodes_per_ring; ++n)
      {
        // Wrap around
        unsigned int np1 = (n == _nodes_per_ring - 1) ? 0 : n + 1;
        Elem * elem = mesh->add_elem(new Tri3);
        elem->set_node(0) = ring_nodes[r][n];
        elem->set_node(1) = ring_nodes[r + 1][n];
        elem->set_node(2) = ring_nodes[r][np1];

        // Add interior faces to 'cylinder' sideset if we are on ring 0.
        if (r == 0)
          mesh->boundary_info->add_side(elem->id(), /*side=*/2, _cylinder_bid);
      }

      // Outer ring (n*, n+1*, n+1)
      for (std::size_t n = 0; n < _nodes_per_ring; ++n)
      {
        // Wrap around
        unsigned int np1 = (n == _nodes_per_ring - 1) ? 0 : n + 1;
        Elem * elem = mesh->add_elem(new Tri3);
        elem->set_node(0) = ring_nodes[r + 1][n];
        elem->set_node(1) = ring_nodes[r + 1][np1];
        elem->set_node(2) = ring_nodes[r][np1];

        // Add exterior faces to 'exterior' sideset if we're on the last ring.
        // Note: this code appears in two places since we could end on either an even or odd ring.
        if (r == _num_rings - 2)
          mesh->boundary_info->add_side(elem->id(), /*side=*/0, _exterior_bid);
      }
    }
    else
    {
      // odd -> even ring
      // Inner ring (n, n+1*, n+1)
      for (std::size_t n = 0; n < _nodes_per_ring; ++n)
      {
        // Wrap around
        unsigned int np1 = (n == _nodes_per_ring - 1) ? 0 : n + 1;
        Elem * elem = mesh->add_elem(new Tri3);
        elem->set_node(0) = ring_nodes[r][n];
        elem->set_node(1) = ring_nodes[r + 1][np1];
        elem->set_node(2) = ring_nodes[r][np1];
      }

      // Outer ring (n*, n+1*, n)
      for (std::size_t n = 0; n < _nodes_per_ring; ++n)
      {
        // Wrap around
        unsigned int np1 = (n == _nodes_per_ring - 1) ? 0 : n + 1;
        Elem * elem = mesh->add_elem(new Tri3);
        elem->set_node(0) = ring_nodes[r + 1][n];
        elem->set_node(1) = ring_nodes[r + 1][np1];
        elem->set_node(2) = ring_nodes[r][n];

        // Add exterior faces to 'exterior' sideset if we're on the last ring.
        if (r == _num_rings - 2)
          mesh->boundary_info->add_side(elem->id(), /*side=*/0, _exterior_bid);
      }
    }
  }

  // Sanity check: make sure all elements have positive area. Note: we
  // can't use elem->volume() for this, as that always returns a
  // positive area regardless of the node ordering.
  // We compute (p1-p0) \cross (p2-p0) and check that the z-component is positive.
  for (const auto & elem : mesh->element_ptr_range())
  {
    Point cp = (elem->point(1) - elem->point(0)).cross(elem->point(2) - elem->point(0));
    if (cp(2) < 0.)
      mooseError("Invalid elem found with negative area");
  }

  // Create sideset names.
  mesh->boundary_info->sideset_name(_cylinder_bid) = "cylinder";
  mesh->boundary_info->sideset_name(_exterior_bid) = "exterior";

  // Find neighbors, etc.
  mesh->prepare_for_use();

  if (_use_tri6)
  {
    mesh->all_second_order(/*full_ordered=*/true);
    std::vector<unsigned int> nos;

    // Loop over the elements, moving mid-edge nodes onto the
    // nearest radius as applicable. For each element, exactly one
    // edge should lie on the same radius, so we move only that
    // mid-edge node.
    for (const auto & elem : mesh->element_ptr_range())
    {
      // Make sure we are dealing only with triangles
      libmesh_assert(elem->n_vertices() == 3);

      // Compute vertex radii
      Real radii[3] = {elem->point(0).norm(), elem->point(1).norm(), elem->point(2).norm()};

      // Compute absolute differences between radii so we can determine which two are on the same
      // circular arc.
      Real dr[3] = {std::abs(radii[0] - radii[1]),
                    std::abs(radii[1] - radii[2]),
                    std::abs(radii[2] - radii[0])};

      // Compute index of minimum dr.
      auto index = std::distance(std::begin(dr), std::min_element(std::begin(dr), std::end(dr)));

      // Make sure that the minimum found is also (almost) zero.
      if (dr[index] > TOLERANCE)
        mooseError("Error: element had no sides with nodes on same radius.");

      // Get list of all local node ids on this side. The first
      // two entries in nos correspond to the vertices, the last
      // entry corresponds to the mid-edge node.
      nos = elem->nodes_on_side(index);

      // Compute the angles associated with nodes nos[0] and nos[1].
      Real theta0 = std::atan2(elem->point(nos[0])(1), elem->point(nos[0])(0)),
           theta1 = std::atan2(elem->point(nos[1])(1), elem->point(nos[1])(0));

      // atan2 returns values in the range (-pi, pi).  If theta0
      // and theta1 have the same sign, we can simply average them
      // to get half of the acute angle between them. On the other
      // hand, if theta0 and theta1 are of opposite sign _and_ both
      // are larger than pi/2, we need to add 2*pi when averaging,
      // otherwise we will get half of the _obtuse_ angle between
      // them, and the point will flip to the other side of the
      // circle (see below).
      Real new_theta = 0.5 * (theta0 + theta1);

      // It should not be possible for both:
      // 1.) |theta0| > pi/2, and
      // 2.) |theta1| < pi/2
      // as this would not be a well-formed element.
      if ((theta0 * theta1 < 0) && (std::abs(theta0) > 0.5 * libMesh::pi) &&
          (std::abs(theta1) > 0.5 * libMesh::pi))
        new_theta = 0.5 * (theta0 + theta1 + 2 * libMesh::pi);

      // The new radius will be the radius of point nos[0] or nos[1] (they are the same!).
      Real new_r = elem->point(nos[0]).norm();

      // Finally, move the point to its new location.
      elem->point(nos[2]) = Point(new_r * std::cos(new_theta), new_r * std::sin(new_theta), 0.);
    }
  }

  return dynamic_pointer_cast<MeshBase>(mesh);
}
Beispiel #20
0
UniquePtr<Elem> InfPrism12::build_side_ptr (const unsigned int i,
                                            bool proxy)
{
  libmesh_assert_less (i, this->n_sides());

  if (proxy)
    {
      switch (i)
        {
          // base
        case 0:
          return UniquePtr<Elem>(new Side<Tri6,InfPrism12>(this,i));

          // ifem sides
        case 1:
        case 2:
        case 3:
          return UniquePtr<Elem>(new Side<InfQuad6,InfPrism12>(this,i));

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }
    }

  else
    {
      // Create NULL pointer to be initialized, returned later.
      Elem * face = libmesh_nullptr;

      switch (i)
        {
        case 0: // the triangular face at z=-1, base face
          {
            face = new Tri6;
            break;
          }

        case 1: // the quad face at y=0
        case 2: // the other quad face
        case 3: // the quad face at x=0
          {
            face = new InfQuad6;
            break;
          }

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }

      face->subdomain_id() = this->subdomain_id();

      // Set the nodes
      for (unsigned n=0; n<face->n_nodes(); ++n)
        face->set_node(n) = this->node_ptr(InfPrism12::side_nodes_map[i][n]);

      return UniquePtr<Elem>(face);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}
Beispiel #21
0
void
AnnularMesh::buildMesh()
{
  const Real dt = (_tmax - _tmin) / _nt;

  MeshBase & mesh = getMesh();
  mesh.clear();
  mesh.set_mesh_dimension(2);
  mesh.set_spatial_dimension(2);
  BoundaryInfo & boundary_info = mesh.get_boundary_info();

  const unsigned num_angular_nodes = (_full_annulus ? _nt : _nt + 1);
  const unsigned num_nodes =
      (_rmin > 0.0 ? (_nr + 1) * num_angular_nodes : _nr * num_angular_nodes + 1);
  const unsigned min_nonzero_layer_num = (_rmin > 0.0 ? 0 : 1);
  std::vector<Node *> nodes(num_nodes);
  unsigned node_id = 0;

  // add nodes at rmax that aren't yet connected to any elements
  Real current_r = _rmax;
  for (unsigned angle_num = 0; angle_num < num_angular_nodes; ++angle_num)
  {
    const Real angle = _tmin + angle_num * dt;
    const Real x = current_r * std::cos(angle);
    const Real y = current_r * std::sin(angle);
    nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id);
    node_id++;
  }

  // add nodes at smaller radii, and connect them with elements
  for (unsigned layer_num = _nr; layer_num > min_nonzero_layer_num; --layer_num)
  {
    if (layer_num == 1)
      current_r = _rmin; // account for precision loss
    else
      current_r -= _len * std::pow(_growth_r, layer_num - 1);

    // add node at angle = _tmin
    nodes[node_id] = mesh.add_point(
        Point(current_r * std::cos(_tmin), current_r * std::sin(_tmin), 0.0), node_id);
    node_id++;
    for (unsigned angle_num = 1; angle_num < num_angular_nodes; ++angle_num)
    {
      const Real angle = _tmin + angle_num * dt;
      const Real x = current_r * std::cos(angle);
      const Real y = current_r * std::sin(angle);
      nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id);
      Elem * elem = mesh.add_elem(new Quad4);
      elem->set_node(0) = nodes[node_id];
      elem->set_node(1) = nodes[node_id - 1];
      elem->set_node(2) = nodes[node_id - num_angular_nodes - 1];
      elem->set_node(3) = nodes[node_id - num_angular_nodes];
      elem->subdomain_id() = _quad_subdomain_id;
      node_id++;

      if (layer_num == _nr)
        // add outer boundary (boundary_id = 1)
        boundary_info.add_side(elem, 2, 1);
      if (layer_num == 1)
        // add inner boundary (boundary_id = 0)
        boundary_info.add_side(elem, 0, 0);
      if (!_full_annulus && angle_num == 1)
        // add tmin boundary (boundary_id = 2)
        boundary_info.add_side(elem, 1, 2);
      if (!_full_annulus && angle_num == num_angular_nodes - 1)
        // add tmin boundary (boundary_id = 3)
        boundary_info.add_side(elem, 3, 3);
    }
    if (_full_annulus)
    {
      // add element connecting to node at angle=0
      Elem * elem = mesh.add_elem(new Quad4);
      elem->set_node(0) = nodes[node_id - num_angular_nodes];
      elem->set_node(1) = nodes[node_id - 1];
      elem->set_node(2) = nodes[node_id - num_angular_nodes - 1];
      elem->set_node(3) = nodes[node_id - 2 * num_angular_nodes];
      elem->subdomain_id() = _quad_subdomain_id;

      if (layer_num == _nr)
        // add outer boundary (boundary_id = 1)
        boundary_info.add_side(elem, 2, 1);
      if (layer_num == 1)
        // add inner boundary (boundary_id = 0)
        boundary_info.add_side(elem, 0, 0);
    }
  }

  // add single node at origin, if relevant
  if (_rmin == 0.0)
  {
    nodes[node_id] = mesh.add_point(Point(0.0, 0.0, 0.0), node_id);
    boundary_info.add_node(node_id, 0); // boundary_id=0 is centre
    for (unsigned angle_num = 0; angle_num < num_angular_nodes - 1; ++angle_num)
    {
      Elem * elem = mesh.add_elem(new Tri3);
      elem->set_node(0) = nodes[node_id];
      elem->set_node(1) = nodes[node_id - num_angular_nodes + angle_num];
      elem->set_node(2) = nodes[node_id - num_angular_nodes + angle_num + 1];
      elem->subdomain_id() = _tri_subdomain_id;
    }
    if (_full_annulus)
    {
      Elem * elem = mesh.add_elem(new Tri3);
      elem->set_node(0) = nodes[node_id];
      elem->set_node(1) = nodes[node_id - 1];
      elem->set_node(2) = nodes[node_id - num_angular_nodes];
      elem->subdomain_id() = _tri_subdomain_id;
    }
  }

  boundary_info.sideset_name(0) = "rmin";
  boundary_info.sideset_name(1) = "rmax";
  boundary_info.nodeset_name(0) = "rmin";
  boundary_info.nodeset_name(1) = "rmax";
  if (!_full_annulus)
  {
    boundary_info.sideset_name(2) = "tmin";
    boundary_info.sideset_name(3) = "tmax";
    boundary_info.nodeset_name(2) = "tmin";
    boundary_info.nodeset_name(3) = "tmax";
  }

  mesh.prepare_for_use(false);
}
Beispiel #22
0
void MatlabIO::read_stream(std::istream& in)
{
  // This is a serial-only process for now;
  // the Mesh should be read on processor 0 and
  // broadcast later
  libmesh_assert_equal_to (this->mesh().processor_id(), 0);

  // Get a reference to the mesh
  MeshBase& the_mesh = MeshInput<MeshBase>::mesh();

  // Clear any existing mesh data
  the_mesh.clear();

  // PDE toolkit only works in 2D
  the_mesh.set_mesh_dimension(2);

#if LIBMESH_DIM < 2
  libMesh::err << "Cannot open dimension 2 mesh file when configured without 2D support." <<
                  std::endl;
  libmesh_error();
#endif

  // Check the input buffer
  libmesh_assert (in.good());

  unsigned int nNodes=0, nElem=0;

  in >> nNodes   // Read the number of nodes
     >> nElem;   // Read the number of elements

  // Sort of check that it worked
  libmesh_assert_greater (nNodes, 0);
  libmesh_assert_greater (nElem, 0);

  // Read the nodal coordinates
  {
    Real x=0., y=0., z=0.;

    for (unsigned int i=0; i<nNodes; i++)
      {
	in >> x   // x-coordinate value
	   >> y;  // y-coordinate value

	the_mesh.add_point ( Point(x,y,z), i);
      }
  }

  // Read the elements (elements)
  {
    unsigned int node=0, dummy=0;

    for (unsigned int i=0; i<nElem; i++)
      {
	Elem* elem = new Tri3; // Always build a triangle
        elem->set_id(i);
	the_mesh.add_elem (elem);

	for (unsigned int n=0; n<3; n++)  // Always read three 3 nodes
	  {
	    in >> node;
	    elem->set_node(n) = the_mesh.node_ptr(node-1);  // Assign the node number
	  }

	// There is an additional subdomain number here,
	// so we read it and get rid of it!
	in >> dummy;
      }
  }

}
Beispiel #23
0
void ExodusII_IO::read (const std::string& fname)
{
  // This is a serial-only process for now;
  // the Mesh should be read on processor 0 and
  // broadcast later
//  libmesh_assert_equal_to (libMesh::processor_id(), 0);

#ifndef LIBMESH_HAVE_EXODUS_API

  libMesh::err <<  "ERROR, ExodusII API is not defined.\n"
	        << "Input file " << fname << " cannot be read"
	        << std::endl;
  libmesh_error();

#else

  // Get a reference to the mesh we are reading
  MeshBase& mesh = MeshInput<MeshBase>::mesh();

  // Clear any existing mesh data
  mesh.clear();

  // Keep track of what kinds of elements this file contains
  elems_of_dimension.clear();
  elems_of_dimension.resize(4, false);

#ifdef DEBUG
  this->verbose(true);
#endif


  ExodusII_IO_Helper::ElementMaps em;     // Instantiate the ElementMaps interface

  exio_helper->open(fname.c_str());       // Open the exodus file, if possible
  exio_helper->read_header();             // Get header information from exodus file
  exio_helper->print_header();            // Print header information

  //assertion fails due to inconsistent mesh dimension
//  libmesh_assert_equal_to (static_cast<unsigned int>(exio_helper->get_num_dim()), mesh.mesh_dimension()); // Be sure number of dimensions
                                                                                // is equal to the number of
                                                                                // dimensions in the mesh supplied.

  exio_helper->read_nodes();                        // Read nodes from the exodus file
  mesh.reserve_nodes(exio_helper->get_num_nodes()); // Reserve space for the nodes.

  // Loop over the nodes, create Nodes with local processor_id 0.
  for (int i=0; i<exio_helper->get_num_nodes(); i++)
    mesh.add_point (Point(exio_helper->get_x(i),
			  exio_helper->get_y(i),
			  exio_helper->get_z(i)), i);

  libmesh_assert_equal_to (static_cast<unsigned int>(exio_helper->get_num_nodes()), mesh.n_nodes());

  exio_helper->read_block_info();                 // Get information about all the blocks
  mesh.reserve_elem(exio_helper->get_num_elem()); // Reserve space for the elements


  // Read in the element connectivity for each block.
  int nelem_last_block = 0;

  std::map<int, unsigned int> exodus_id_to_mesh_id;

  // Loop over all the blocks
  for (int i=0; i<exio_helper->get_num_elem_blk(); i++)
    {
      // Read the information for block i
      exio_helper->read_elem_in_block (i);
      int subdomain_id = exio_helper->get_block_id(i);

      // populate the map of names
      mesh.subdomain_name(static_cast<subdomain_id_type>(subdomain_id)) =
        exio_helper->get_block_name(i);

      // Set any relevant node/edge maps for this element
      const std::string type_str (exio_helper->get_elem_type());
      const ExodusII_IO_Helper::Conversion conv = em.assign_conversion(type_str);
      //if (_verbose)
      //libMesh::out << "Reading a block of " << type_str << " elements." << std::endl;

      // Loop over all the faces in this block
      int jmax = nelem_last_block+exio_helper->get_num_elem_this_blk();
      for (int j=nelem_last_block; j<jmax; j++)
	{
	  Elem* elem = Elem::build (conv.get_canonical_type()).release();
	  libmesh_assert (elem);
          elem->subdomain_id() = static_cast<subdomain_id_type>(subdomain_id) ;
          //elem->set_id(j);// Don't try to second guess the Element ID setting scheme!

          elems_of_dimension[elem->dim()] = true;

	  elem = mesh.add_elem (elem); // Catch the Elem pointer that the Mesh throws back

          exodus_id_to_mesh_id[j+1] = elem->id();

	  // Set all the nodes for this element
	  for (int k=0; k<exio_helper->get_num_nodes_per_elem(); k++)
	    {
	      int gi = (j-nelem_last_block)*exio_helper->get_num_nodes_per_elem() + conv.get_node_map(k); // global index
	      int node_number   = exio_helper->get_connect(gi);             // Global node number (1-based)
	      elem->set_node(k) = mesh.node_ptr((node_number-1)); // Set node number
	                                                          // Subtract 1 since
		                                                  // exodus is internally 1-based
	    }
	}

      // running sum of # of elements per block,
      // (should equal total number of elements in the end)
      nelem_last_block += exio_helper->get_num_elem_this_blk();
    }
  libmesh_assert_equal_to (static_cast<unsigned int>(nelem_last_block), mesh.n_elem());

   // Set the mesh dimension to the largest encountered for an element
  for (unsigned int i=0; i!=4; ++i)
    if (elems_of_dimension[i])
      mesh.set_mesh_dimension(i);

  // Read in sideset information -- this is useful for applying boundary conditions
  {
    exio_helper->read_sideset_info(); // Get basic information about ALL sidesets
    int offset=0;
    for (int i=0; i<exio_helper->get_num_side_sets(); i++)
      {
	offset += (i > 0 ? exio_helper->get_num_sides_per_set(i-1) : 0); // Compute new offset
	exio_helper->read_sideset (i, offset);

        mesh.boundary_info->sideset_name(exio_helper->get_side_set_id(i)) =
          exio_helper->get_side_set_name(i);
      }

    const std::vector<int>& elem_list = exio_helper->get_elem_list();
    const std::vector<int>& side_list = exio_helper->get_side_list();
    const std::vector<int>& id_list   = exio_helper->get_id_list();

    for (unsigned int e=0; e<elem_list.size(); e++)
      {
	// Set any relevant node/edge maps for this element

        Elem * elem = mesh.elem(exodus_id_to_mesh_id[elem_list[e]]);

	const ExodusII_IO_Helper::Conversion conv =
	  em.assign_conversion(elem->type());

	mesh.boundary_info->add_side (exodus_id_to_mesh_id[elem_list[e]],
				      conv.get_side_map(side_list[e]-1),
				      id_list[e]);
      }
  }

  // Read nodeset info
  {
    exio_helper->read_nodeset_info();

    for (int nodeset=0; nodeset<exio_helper->get_num_node_sets(); nodeset++)
      {
        int nodeset_id = exio_helper->get_nodeset_id(nodeset);

        mesh.boundary_info->nodeset_name(nodeset_id) =
          exio_helper->get_node_set_name(nodeset);

        exio_helper->read_nodeset(nodeset);

        const std::vector<int>& node_list = exio_helper->get_node_list();

        for(unsigned int node=0; node<node_list.size(); node++)
          mesh.boundary_info->add_node(node_list[node]-1, nodeset_id);
      }
  }

#if LIBMESH_DIM < 3
  if (mesh.mesh_dimension() > LIBMESH_DIM)
    {
      libMesh::err << "Cannot open dimension " <<
		      mesh.mesh_dimension() <<
		      " mesh file when configured without " <<
                      mesh.mesh_dimension() << "D support." <<
                      std::endl;
      libmesh_error();
    }
#endif

#endif
}
Beispiel #24
0
UniquePtr<Elem> Prism::side (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_sides());

  Elem* face = NULL;

  switch (i)
    {
    case 0:  // the triangular face at z=0
      {
        face = new Tri3;

        face->set_node(0) = this->get_node(0);
        face->set_node(1) = this->get_node(2);
        face->set_node(2) = this->get_node(1);

        break;
      }
    case 1:  // the quad face at y=0
      {
        face = new Quad4;

        face->set_node(0) = this->get_node(0);
        face->set_node(1) = this->get_node(1);
        face->set_node(2) = this->get_node(4);
        face->set_node(3) = this->get_node(3);

        break;
      }
    case 2:  // the other quad face
      {
        face = new Quad4;

        face->set_node(0) = this->get_node(1);
        face->set_node(1) = this->get_node(2);
        face->set_node(2) = this->get_node(5);
        face->set_node(3) = this->get_node(4);

        break;
      }
    case 3: // the quad face at x=0
      {
        face = new Quad4;

        face->set_node(0) = this->get_node(2);
        face->set_node(1) = this->get_node(0);
        face->set_node(2) = this->get_node(3);
        face->set_node(3) = this->get_node(5);

        break;
      }
    case 4: // the triangular face at z=1
      {
        face = new Tri3;

        face->set_node(0) = this->get_node(3);
        face->set_node(1) = this->get_node(4);
        face->set_node(2) = this->get_node(5);

        break;
      }
    default:
      libmesh_error_msg("Invalid side i = " << i);
    }

  return UniquePtr<Elem>(face);
}
  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();
  }
Beispiel #26
0
void VTKIO::read (const std::string& name)
{
  // This is a serial-only process for now;
  // the Mesh should be read on processor 0 and
  // broadcast later
  libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0);

  // Keep track of what kinds of elements this file contains
  elems_of_dimension.clear();
  elems_of_dimension.resize(4, false);

#ifndef LIBMESH_HAVE_VTK
  libMesh::err << "Cannot read VTK file: " << name
               << "\nYou must have VTK installed and correctly configured to read VTK meshes."
               << std::endl;
  libmesh_error();

#else
  // Use a typedef, because these names are just crazy
  typedef vtkSmartPointer<vtkXMLUnstructuredGridReader> MyReader;
  MyReader reader = MyReader::New();

  // Pass the filename along to the reader
  reader->SetFileName( name.c_str() );

  // Force reading
  reader->Update();

  // read in the grid
  _vtk_grid = reader->GetOutput();
  // _vtk_grid->Update(); // FIXME: Necessary?

  // Get a reference to the mesh
  MeshBase& mesh = MeshInput<MeshBase>::mesh();

  // Clear out any pre-existing data from the Mesh
  mesh.clear();

  // Get the number of points from the _vtk_grid object
  const unsigned int vtk_num_points = static_cast<unsigned int>(_vtk_grid->GetNumberOfPoints());

  // always numbered nicely??, so we can loop like this
  // I'm pretty sure it is numbered nicely
  for (unsigned int i=0; i<vtk_num_points; ++i)
    {
      // add to the id map
      // and add the actual point
      double * pnt = _vtk_grid->GetPoint(static_cast<vtkIdType>(i));
      Point xyz(pnt[0], pnt[1], pnt[2]);
      Node* newnode = mesh.add_point(xyz, i);

      // Add node to the nodes vector &
      // tell the MeshData object the foreign node id.
      if (this->_mesh_data != NULL)
        this->_mesh_data->add_foreign_node_id (newnode, i);
    }

  // Get the number of cells from the _vtk_grid object
  const unsigned int vtk_num_cells = static_cast<unsigned int>(_vtk_grid->GetNumberOfCells());

  for (unsigned int i=0; i<vtk_num_cells; ++i)
    {
      vtkCell* cell = _vtk_grid->GetCell(i);
      Elem* elem = NULL;
      switch (cell->GetCellType())
        {
        case VTK_LINE:
          elem = new Edge2;
          break;
        case VTK_QUADRATIC_EDGE:
          elem = new Edge3;
          break;
        case VTK_TRIANGLE:
          elem = new Tri3();
          break;
        case VTK_QUADRATIC_TRIANGLE:
          elem = new Tri6();
          break;
        case VTK_QUAD:
          elem = new Quad4();
          break;
        case VTK_QUADRATIC_QUAD:
          elem = new Quad8();
          break;
#if VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0)
        case VTK_BIQUADRATIC_QUAD:
          elem = new Quad9();
          break;
#endif
        case VTK_TETRA:
          elem = new Tet4();
          break;
        case VTK_QUADRATIC_TETRA:
          elem = new Tet10();
          break;
        case VTK_WEDGE:
          elem = new Prism6();
          break;
        case VTK_QUADRATIC_WEDGE:
          elem = new Prism15();
          break;
        case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
          elem = new Prism18();
          break;
        case VTK_HEXAHEDRON:
          elem = new Hex8();
          break;
        case VTK_QUADRATIC_HEXAHEDRON:
          elem = new Hex20();
          break;
        case VTK_TRIQUADRATIC_HEXAHEDRON:
          elem = new Hex27();
          break;
        case VTK_PYRAMID:
          elem = new Pyramid5();
          break;
        default:
          libMesh::err << "element type not implemented in vtkinterface " << cell->GetCellType() << std::endl;
          libmesh_error();
          break;
        }

      // get the straightforward numbering from the VTK cells
      for (unsigned int j=0; j<elem->n_nodes(); ++j)
        elem->set_node(j) = mesh.node_ptr(cell->GetPointId(j));

      // then get the connectivity
      std::vector<dof_id_type> conn;
      elem->connectivity(0, VTK, conn);

      // then reshuffle the nodes according to the connectivity, this
      // two-time-assign would evade the definition of the vtk_mapping
      for (unsigned int j=0; j<conn.size(); ++j)
        elem->set_node(j) = mesh.node_ptr(conn[j]);

      elem->set_id(i);

      elems_of_dimension[elem->dim()] = true;

      mesh.add_elem(elem);
    } // end loop over VTK cells

  // Set the mesh dimension to the largest encountered for an element
  for (unsigned int i=0; i!=4; ++i)
    if (elems_of_dimension[i])
      mesh.set_mesh_dimension(i);

#if LIBMESH_DIM < 3
  if (mesh.mesh_dimension() > LIBMESH_DIM)
    {
      libMesh::err << "Cannot open dimension " <<
        mesh.mesh_dimension() <<
        " mesh file when configured without " <<
        mesh.mesh_dimension() << "D support." <<
        std::endl;
      libmesh_error();
    }
#endif

#endif // LIBMESH_HAVE_VTK
}
Beispiel #27
0
UniquePtr<Elem> InfHex8::build_side (const unsigned int i,
                                     bool proxy) const
{
  libmesh_assert_less (i, this->n_sides());

  if (proxy)
    {
      switch (i)
        {
          // base
        case 0:
          return UniquePtr<Elem>(new Side<Quad4,InfHex8>(this,i));

          // ifem sides
        case 1:
        case 2:
        case 3:
        case 4:
          return UniquePtr<Elem>(new Side<InfQuad4,InfHex8>(this,i));

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }
    }

  else
    {
      // Create NULL pointer to be initialized, returned later.
      Elem* face = NULL;

      // Think of a unit cube: (-1,1) x (-1,1) x (1,1)
      switch (i)
        {
        case 0: // the base face
          {
            face = new Quad4;

            // Only here, the face element's normal points inward
            face->set_node(0) = this->get_node(0);
            face->set_node(1) = this->get_node(1);
            face->set_node(2) = this->get_node(2);
            face->set_node(3) = this->get_node(3);

            break;
          }

        case 1:  // connecting to another infinite element
          {
            face = new InfQuad4;

            face->set_node(0) = this->get_node(0);
            face->set_node(1) = this->get_node(1);
            face->set_node(2) = this->get_node(4);
            face->set_node(3) = this->get_node(5);

            break;
          }

        case 2:  // connecting to another infinite element
          {
            face = new InfQuad4;

            face->set_node(0) = this->get_node(1);
            face->set_node(1) = this->get_node(2);
            face->set_node(2) = this->get_node(5);
            face->set_node(3) = this->get_node(6);

            break;
          }

        case 3:  // connecting to another infinite element
          {
            face = new InfQuad4;

            face->set_node(0) = this->get_node(2);
            face->set_node(1) = this->get_node(3);
            face->set_node(2) = this->get_node(6);
            face->set_node(3) = this->get_node(7);

            break;
          }

        case 4:  // connecting to another infinite element
          {
            face = new InfQuad4;

            face->set_node(0) = this->get_node(3);
            face->set_node(1) = this->get_node(0);
            face->set_node(2) = this->get_node(7);
            face->set_node(3) = this->get_node(4);

            break;
          }

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }

      face->subdomain_id() = this->subdomain_id();
      return UniquePtr<Elem>(face);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}
std::unique_ptr<MeshBase>
SphereSurfaceMeshGenerator::generate()
{
  // Have MOOSE construct the correct libMesh::Mesh object using Mesh block and CLI parameters.
  auto mesh = _mesh->buildMeshBaseObject();
  mesh->set_mesh_dimension(2);
  mesh->set_spatial_dimension(3);

  const Sphere sphere(_center, _radius);

  // icosahedron points (using golden ratio rectangle construction)
  const Real phi = (1.0 + std::sqrt(5.0)) / 2.0;
  const Real X = std::sqrt(1.0 / (phi * phi + 1.0));
  const Real Z = X * phi;
  const Point vdata[12] = {{-X, 0.0, Z},
                           {X, 0.0, Z},
                           {-X, 0.0, -Z},
                           {X, 0.0, -Z},
                           {0.0, Z, X},
                           {0.0, Z, -X},
                           {0.0, -Z, X},
                           {0.0, -Z, -X},
                           {Z, X, 0.0},
                           {-Z, X, 0.0},
                           {Z, -X, 0.0},
                           {-Z, -X, 0.0}};
  for (unsigned int i = 0; i < 12; ++i)
    mesh->add_point(vdata[i] * _radius + _center, i);

  // icosahedron faces
  const unsigned int tindices[20][3] = {{0, 4, 1},  {0, 9, 4},  {9, 5, 4},  {4, 5, 8},  {4, 8, 1},
                                        {8, 10, 1}, {8, 3, 10}, {5, 3, 8},  {5, 2, 3},  {2, 7, 3},
                                        {7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6},
                                        {6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5},  {7, 2, 11}};
  for (unsigned int i = 0; i < 20; ++i)
  {
    Elem * elem = mesh->add_elem(new Tri3);
    elem->set_node(0) = mesh->node_ptr(tindices[i][0]);
    elem->set_node(1) = mesh->node_ptr(tindices[i][1]);
    elem->set_node(2) = mesh->node_ptr(tindices[i][2]);
  }

  // we need to prepare distributed meshes before using refinement
  if (!mesh->is_replicated())
    mesh->prepare_for_use(/*skip_renumber =*/false);

  // Now we have the beginnings of a sphere.
  // Add some more elements by doing uniform refinements and
  // popping nodes to the boundary.
  MeshRefinement mesh_refinement(*mesh);

  // Loop over the elements, refine, pop nodes to boundary.
  for (unsigned int r = 0; r < _depth; ++r)
  {
    mesh_refinement.uniformly_refine(1);

    auto it = mesh->active_nodes_begin();
    const auto end = mesh->active_nodes_end();

    for (; it != end; ++it)
    {
      Node & node = **it;
      node = sphere.closest_point(node);
    }
  }

  // Flatten the AMR mesh to get rid of inactive elements
  MeshTools::Modification::flatten(*mesh);

  return dynamic_pointer_cast<MeshBase>(mesh);
}
UniquePtr<Elem> InfPrism6::build_side (const unsigned int i,
                                       bool proxy) const
{
  libmesh_assert_less (i, this->n_sides());

  if (proxy)
    {
      switch (i)
        {
          // base
        case 0:
          return UniquePtr<Elem>(new Side<Tri3,InfPrism6>(this,i));

          // ifem sides
        case 1:
        case 2:
        case 3:
          return UniquePtr<Elem>(new Side<InfQuad4,InfPrism6>(this,i));

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }
    }

  else
    {
      // Create NULL pointer to be initialized, returned later.
      Elem* face = NULL;

      switch (i)
        {
        case 0:  // the triangular face at z=-1, base face
          {
            face = new Tri3;

            // Note that for this face element, the normal points inward
            face->set_node(0) = this->get_node(0);
            face->set_node(1) = this->get_node(1);
            face->set_node(2) = this->get_node(2);

            break;
          }

        case 1:  // the quad face at y=0
          {
            face = new InfQuad4;

            face->set_node(0) = this->get_node(0);
            face->set_node(1) = this->get_node(1);
            face->set_node(2) = this->get_node(3);
            face->set_node(3) = this->get_node(4);

            break;
          }

        case 2:  // the other quad face
          {
            face = new InfQuad4;

            face->set_node(0) = this->get_node(1);
            face->set_node(1) = this->get_node(2);
            face->set_node(2) = this->get_node(4);
            face->set_node(3) = this->get_node(5);

            break;
          }

        case 3: // the quad face at x=0
          {
            face = new InfQuad4;

            face->set_node(0) = this->get_node(2);
            face->set_node(1) = this->get_node(0);
            face->set_node(2) = this->get_node(5);
            face->set_node(3) = this->get_node(3);

            break;
          }

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }

      face->subdomain_id() = this->subdomain_id();
      return UniquePtr<Elem>(face);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}
Beispiel #30
0
void Elem::refine (MeshRefinement& mesh_refinement)
{
  libmesh_assert (this->refinement_flag() == Elem::REFINE);
  libmesh_assert (this->active());

  // Create my children if necessary
  if (!_children)
    {
      _children = new Elem*[this->n_children()];

      unsigned int parent_p_level = this->p_level();
      for (unsigned int c=0; c<this->n_children(); c++)
        {
	  _children[c] = Elem::build(this->type(), this).release();
	  _children[c]->set_refinement_flag(Elem::JUST_REFINED);
	  _children[c]->set_p_level(parent_p_level);
	  _children[c]->set_p_refinement_flag(this->p_refinement_flag());
        }

      // Compute new nodal locations
      // and asssign nodes to children
      // Make these static.  It is unlikely the
      // sizes will change from call to call, so having these
      // static should save on reallocations
      std::vector<std::vector<Point> >        p    (this->n_children());
      std::vector<std::vector<Node*> >        nodes(this->n_children());


      // compute new nodal locations
      for (unsigned int c=0; c<this->n_children(); c++)
        {
          Elem *child = this->child(c);
	  p[c].resize    (child->n_nodes());
	  nodes[c].resize(child->n_nodes());

	  for (unsigned int nc=0; nc<child->n_nodes(); nc++)
	    {
	      // zero entries
	      p[c][nc].zero();
	      nodes[c][nc] = NULL;

	      for (unsigned int n=0; n<this->n_nodes(); n++)
	        {
		  // The value from the embedding matrix
		  const float em_val = this->embedding_matrix(c,nc,n);

		  if (em_val != 0.)
		    {
		      p[c][nc].add_scaled (this->point(n), em_val);

		      // We may have found the node, in which case we
		      // won't need to look it up later.
		      if (em_val == 1.)
		        nodes[c][nc] = this->get_node(n);
		    }
	        }
	    }

	// assign nodes to children & add them to the mesh
          const Real pointtol = this->hmin() * TOLERANCE;
	  for (unsigned int nc=0; nc<child->n_nodes(); nc++)
	    {
	      if (nodes[c][nc] != NULL)
	        {
		  child->set_node(nc) = nodes[c][nc];
	        }
	      else
	        {
		  child->set_node(nc) =
		    mesh_refinement.add_point(p[c][nc],
					      child->processor_id(),
                                              pointtol);
		  child->get_node(nc)->set_n_systems
                    (this->n_systems());
	        }
	    }

	  mesh_refinement.add_elem (child);
          child->set_n_systems(this->n_systems());
        }
    }
  else
    {
      unsigned int parent_p_level = this->p_level();
      for (unsigned int c=0; c<this->n_children(); c++)
        {
          Elem *child = this->child(c);
          libmesh_assert(child->subactive());
          child->set_refinement_flag(Elem::JUST_REFINED);
          child->set_p_level(parent_p_level);
          child->set_p_refinement_flag(this->p_refinement_flag());
        }
    }

  // Un-set my refinement flag now
  this->set_refinement_flag(Elem::INACTIVE);
  this->set_p_refinement_flag(Elem::INACTIVE);

  for (unsigned int c=0; c<this->n_children(); c++)
    {
      libmesh_assert(this->child(c)->parent() == this);
      libmesh_assert(this->child(c)->active());
    }
  libmesh_assert (this->ancestor());
}