Exemplo n.º 1
0
  void testMesh()
  {
    // There'd better be 3 elements
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)3, _mesh->n_elem() );

    // There'd better be only 6 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)6, _mesh->n_nodes() );

    /* The nodes for the EDGE2 element should have the same global ids
       as the bottom edge of the top QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(0), _mesh->elem(0)->node(0) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(1), _mesh->elem(0)->node(1) );

    /* The nodes for the EDGE2 element should have the same global ids
       as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(0), _mesh->elem(1)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(1), _mesh->elem(1)->node(2) );

    /* The nodes for the bottom edge of the top QUAD4 element should have
       the same global ids as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(0)->node(0), _mesh->elem(1)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(0)->node(1), _mesh->elem(1)->node(2) );

    // We didn't set an interior_parent on the edge element, so it
    // should default to NULL
    CPPUNIT_ASSERT( !_mesh->elem(2)->interior_parent() );
  }
Exemplo n.º 2
0
  void testMesh()
  {
    // There'd better be 3 elements
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)3, _mesh->n_elem() );

    // There'd better be only 6 nodes
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)6, _mesh->n_nodes() );

    /* The nodes for the EDGE2 element should have the same global ids
       as the bottom edge of the top QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(0), _mesh->elem(0)->node(0) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(1), _mesh->elem(0)->node(1) );

    /* The nodes for the EDGE2 element should have the same global ids
       as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(0), _mesh->elem(1)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(2)->node(1), _mesh->elem(1)->node(2) );

    /* The nodes for the bottom edge of the top QUAD4 element should have
       the same global ids as the top edge of the bottom QUAD4 element */
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(0)->node(0), _mesh->elem(1)->node(3) );
    CPPUNIT_ASSERT_EQUAL( _mesh->elem(0)->node(1), _mesh->elem(1)->node(2) );
  }
Exemplo n.º 3
0
// Begin the main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  LibMeshInit init (argc, argv);

  // Skip this 3D example if libMesh was compiled as 1D/2D-only.
  libmesh_example_requires (3 == LIBMESH_DIM, "3D support");

  // Skip this example without --enable-node-valence
#ifndef LIBMESH_ENABLE_NODE_VALENCE
  libmesh_example_requires (false, "--enable-node-valence");
#endif

  // Skip this example without --enable-amr; requires MeshRefinement
#ifndef LIBMESH_ENABLE_AMR
  libmesh_example_requires(false, "--enable-amr");
#else

  // Skip this example without --enable-second; requires d2phi
#ifndef LIBMESH_ENABLE_SECOND_DERIVATIVES
  libmesh_example_requires(false, "--enable-second");
#else

  // Create a 2D mesh distributed across the default MPI communicator.
  // Subdivision surfaces do not appear to work with ParallelMesh yet.
  SerialMesh mesh (init.comm(), 2);

  // Read the coarse square mesh.
  mesh.read ("square_mesh.off");

  // Resize the square plate to edge length L.
  const Real L = 100.;
  MeshTools::Modification::scale(mesh, L, L, L);

  // Quadrisect the mesh triangles a few times to obtain a
  // finer mesh.  Subdivision surface elements require the
  // refinement data to be removed afterwards.
  MeshRefinement mesh_refinement (mesh);
  mesh_refinement.uniformly_refine (3);
  MeshTools::Modification::flatten (mesh);

  // Write the mesh before the ghost elements are added.
#if defined(LIBMESH_HAVE_VTK)
  VTKIO(mesh).write ("without_ghosts.pvtu");
#endif
#if defined(LIBMESH_HAVE_EXODUS_API)
  ExodusII_IO(mesh).write ("without_ghosts.e");
#endif

  // Print information about the triangulated mesh to the screen.
  mesh.print_info();

  // Turn the triangulated mesh into a subdivision mesh
  // and add an additional row of "ghost" elements around
  // it in order to complete the extended local support of
  // the triangles at the boundaries.  If the second
  // argument is set to true, the outermost existing
  // elements are converted into ghost elements, and the
  // actual physical mesh is thus getting smaller.
  MeshTools::Subdivision::prepare_subdivision_mesh (mesh, false);

  // Print information about the subdivision mesh to the screen.
  mesh.print_info();

  // Write the mesh with the ghost elements added.
  // Compare this to the original mesh to see the difference.
#if defined(LIBMESH_HAVE_VTK)
  VTKIO(mesh).write ("with_ghosts.pvtu");
#endif
#if defined(LIBMESH_HAVE_EXODUS_API)
  ExodusII_IO(mesh).write ("with_ghosts.e");
#endif

  // Create an equation systems object.
  EquationSystems equation_systems (mesh);

  // Declare the system and its variables.
  // Create a linear implicit system named "Shell".
  LinearImplicitSystem & system = equation_systems.add_system<LinearImplicitSystem> ("Shell");

  // Add the three translational deformation variables
  // "u", "v", "w" to "Shell".  Since subdivision shell
  // elements meet the C1-continuity requirement, no
  // rotational or other auxiliary variables are needed.
  // Loop Subdivision Elements are always interpolated
  // by quartic box splines, hence the order must always
  // be \p FOURTH.
  system.add_variable ("u", FOURTH, SUBDIVISION);
  system.add_variable ("v", FOURTH, SUBDIVISION);
  system.add_variable ("w", FOURTH, SUBDIVISION);

  // Give the system a pointer to the matrix and rhs assembly
  // function.
  system.attach_assemble_function (assemble_shell);

  // Use the parameters of the equation systems object to
  // tell the shell system about the material properties, the
  // shell thickness, and the external load.
  const Real h  = 1.;
  const Real E  = 1.e7;
  const Real nu = 0.;
  const Real q  = 1.;
  equation_systems.parameters.set<Real> ("thickness")       = h;
  equation_systems.parameters.set<Real> ("young's modulus") = E;
  equation_systems.parameters.set<Real> ("poisson ratio")   = nu;
  equation_systems.parameters.set<Real> ("uniform load")    = q;

  // Initialize the data structures for the equation system.
  equation_systems.init();

  // Print information about the system to the screen.
  equation_systems.print_info();

  // Solve the linear system.
  system.solve();

  // After solving the system, write the solution to a VTK
  // or ExodusII output file ready for import in, e.g.,
  // Paraview.
#if defined(LIBMESH_HAVE_VTK)
  VTKIO(mesh).write_equation_systems ("out.pvtu", equation_systems);
#endif
#if defined(LIBMESH_HAVE_EXODUS_API)
  ExodusII_IO(mesh).write_equation_systems ("out.e", equation_systems);
#endif

  // Find the center node to measure the maximum deformation of the plate.
  Node* center_node = 0;
  Real nearest_dist_sq = mesh.point(0).size_sq();
  for (unsigned int nid=1; nid<mesh.n_nodes(); ++nid)
  {
    const Real dist_sq = mesh.point(nid).size_sq();
    if (dist_sq < nearest_dist_sq)
    {
      nearest_dist_sq = dist_sq;
      center_node = mesh.node_ptr(nid);
    }
  }

  // Finally, we evaluate the z-displacement "w" at the center node.
  const unsigned int w_var = system.variable_number ("w");
  dof_id_type w_dof = center_node->dof_number (system.number(), w_var, 0);
  Number w = 0;
  if (w_dof >= system.get_dof_map().first_dof() &&
      w_dof <  system.get_dof_map().end_dof())
    w = system.current_solution(w_dof);
  system.comm().sum(w);


  // The analytic solution for the maximum displacement of
  // a clamped square plate in pure bending, from Taylor,
  // Govindjee, Commun. Numer. Meth. Eng. 20, 757-765, 2004.
  const Real D = E * h*h*h / (12*(1-nu*nu));
  const Real w_analytic = 0.001265319 * L*L*L*L * q / D;

  // Print the finite element solution and the analytic
  // prediction of the maximum displacement of the clamped
  // square plate to the screen.
  std::cout << "z-displacement of the center point: " << w << std::endl;
  std::cout << "Analytic solution for pure bending: " << w_analytic << std::endl;

#endif // #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES

#endif // #ifdef LIBMESH_ENABLE_AMR

  // All done.
  return 0;
}