void testDofOrdering()
  {
    EquationSystems es(*_mesh);
    es.add_system<LinearImplicitSystem>("TestDofSystem");
    es.get_system("TestDofSystem").add_variable("u",FIRST);
    es.init();

    DofMap& dof_map = es.get_system("TestDofSystem").get_dof_map();

    std::vector<dof_id_type> top_quad_dof_indices, bottom_quad_dof_indices, edge_dof_indices;

    dof_map.dof_indices( _mesh->elem(0), top_quad_dof_indices );
    dof_map.dof_indices( _mesh->elem(1), bottom_quad_dof_indices );
    dof_map.dof_indices( _mesh->elem(2), edge_dof_indices );

    /* The dofs for the EDGE2 element should be the same
       as the bottom edge of the top QUAD4 dofs */
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[0], top_quad_dof_indices[0] );
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[1], top_quad_dof_indices[1] );

    /* The dofs for the EDGE2 element should be the same
       as the top edge of the bottom QUAD4 dofs */
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[0], bottom_quad_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( edge_dof_indices[1], bottom_quad_dof_indices[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( top_quad_dof_indices[0], bottom_quad_dof_indices[3] );
    CPPUNIT_ASSERT_EQUAL( top_quad_dof_indices[1], bottom_quad_dof_indices[2] );
  }
  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() );
  }
  void testPointLocatorTree()
  {
    UniquePtr<PointLocatorBase> locator = _mesh->sub_point_locator();

    Point top_point(0.5, 0.5);
    const Elem* top_elem = (*locator)(top_point);
    CPPUNIT_ASSERT(top_elem);

    // We should have gotten back the top quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)0, top_elem->id() );

    Point bottom_point(0.5, -0.5);
    const Elem* bottom_elem = (*locator)(bottom_point);
    CPPUNIT_ASSERT(bottom_elem);

    // We should have gotten back the bottom quad
    CPPUNIT_ASSERT_EQUAL( (dof_id_type)1, bottom_elem->id() );

    // Test getting back the edge
    {
      std::set<subdomain_id_type> subdomain_id; subdomain_id.insert(1);
      Point interface_point( 0.5, 0.0 );
      const Elem* interface_elem = (*locator)(interface_point, &subdomain_id);
      CPPUNIT_ASSERT(interface_elem);

      // We should have gotten back the overlapping edge element
      CPPUNIT_ASSERT_EQUAL( (dof_id_type)2, interface_elem->id() );
    }
  }
  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) );
  }
  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*/);
  }
Exemple #6
0
int main (int argc, char ** argv)
{
  // Initialize libMesh.
  LibMeshInit init (argc, argv);

#if !defined(LIBMESH_HAVE_XDR)
  // We need XDR support to write out reduced bases
  libmesh_example_requires(false, "--enable-xdr");
#elif defined(LIBMESH_DEFAULT_SINGLE_PRECISION)
  // XDR binary support requires double precision
  libmesh_example_requires(false, "double precision");
#elif defined(LIBMESH_DEFAULT_TRIPLE_PRECISION)
  // I have no idea why long double isn't working here... [RHS]
  libmesh_example_requires(false, "double precision");
#endif

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

  // Define the names of the input files we will read the problem properties from
  std::string eim_parameters = "eim.in";
  std::string rb_parameters  = "rb.in";
  std::string main_parameters = "reduced_basis_ex4.in";
  GetPot infile(main_parameters);

  unsigned int n_elem = infile("n_elem", 1);       // Determines the number of elements in the "truth" mesh
  const unsigned int dim = 2;                      // The number of spatial dimensions
  bool store_basis_functions = infile("store_basis_functions", false); // Do we write out basis functions?

  // Read the "online_mode" flag from the command line
  GetPot command_line (argc, argv);
  int online_mode = 0;
  if (command_line.search(1, "-online_mode"))
    online_mode = command_line.next(online_mode);

  // Create a mesh (just a simple square) on the default MPI
  // communicator.  We currently have to create a SerialMesh here due
  // to a reduced_basis regression with ParallelMesh
  SerialMesh mesh (init.comm(), dim);
  MeshTools::Generation::build_square (mesh,
                                       n_elem, n_elem,
                                       -1., 1.,
                                       -1., 1.,
                                       QUAD4);

  // Initialize the EquationSystems object for this mesh and attach
  // the EIM and RB Construction objects
  EquationSystems equation_systems (mesh);

  SimpleEIMConstruction & eim_construction =
    equation_systems.add_system<SimpleEIMConstruction> ("EIM");
  SimpleRBConstruction & rb_construction =
    equation_systems.add_system<SimpleRBConstruction> ("RB");

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

  // Print out some information about the "truth" discretization
  mesh.print_info();
  equation_systems.print_info();

  // Initialize the standard RBEvaluation object
  SimpleRBEvaluation rb_eval(mesh.comm());

  // Initialize the EIM RBEvaluation object
  SimpleEIMEvaluation eim_rb_eval(mesh.comm());

  // Set the rb_eval objects for the RBConstructions
  eim_construction.set_rb_evaluation(eim_rb_eval);
  rb_construction.set_rb_evaluation(rb_eval);

  if (!online_mode)
    {
      // Read data from input file and print state
      eim_construction.process_parameters_file(eim_parameters);
      eim_construction.print_info();

      // Perform the EIM Greedy and write out the data
      eim_construction.initialize_rb_construction();
      eim_construction.train_reduced_basis();

#if defined(LIBMESH_HAVE_CAPNPROTO)
      RBDataSerialization::RBEIMEvaluationSerialization rb_eim_eval_writer(eim_rb_eval);
      rb_eim_eval_writer.write_to_file("rb_eim_eval.bin");
#else
      eim_construction.get_rb_evaluation().legacy_write_offline_data_to_files("eim_data");
#endif

      // Read data from input file and print state
      rb_construction.process_parameters_file(rb_parameters);

      // attach the EIM theta objects to the RBConstruction and RBEvaluation objects
      eim_rb_eval.initialize_eim_theta_objects();
      rb_eval.get_rb_theta_expansion().attach_multiple_F_theta(eim_rb_eval.get_eim_theta_objects());

      // attach the EIM assembly objects to the RBConstruction object
      eim_construction.initialize_eim_assembly_objects();
      rb_construction.get_rb_assembly_expansion().attach_multiple_F_assembly(eim_construction.get_eim_assembly_objects());

      // Print out the state of rb_construction now that the EIM objects have been attached
      rb_construction.print_info();

      // Need to initialize _after_ EIM greedy so that
      // the system knows how many affine terms there are
      rb_construction.initialize_rb_construction();
      rb_construction.train_reduced_basis();

#if defined(LIBMESH_HAVE_CAPNPROTO)
      RBDataSerialization::RBEvaluationSerialization rb_eval_writer(rb_construction.get_rb_evaluation());
      rb_eval_writer.write_to_file("rb_eval.bin");
#else
      rb_construction.get_rb_evaluation().legacy_write_offline_data_to_files("rb_data");
#endif

      // Write out the basis functions, if requested
      if (store_basis_functions)
        {
          // Write out the basis functions
          eim_construction.get_rb_evaluation().write_out_basis_functions(
            eim_construction.get_explicit_system(), "eim_data");
          rb_construction.get_rb_evaluation().write_out_basis_functions(
            rb_construction, "rb_data");
        }
    }
  else
    {
#if defined(LIBMESH_HAVE_CAPNPROTO)
      RBDataDeserialization::RBEIMEvaluationDeserialization rb_eim_eval_reader(eim_rb_eval);
      rb_eim_eval_reader.read_from_file("rb_eim_eval.bin");
#else
      eim_rb_eval.legacy_read_offline_data_from_files("eim_data");
#endif

      // attach the EIM theta objects to rb_eval objects
      eim_rb_eval.initialize_eim_theta_objects();
      rb_eval.get_rb_theta_expansion().attach_multiple_F_theta(eim_rb_eval.get_eim_theta_objects());

      // Read in the offline data for rb_eval
#if defined(LIBMESH_HAVE_CAPNPROTO)
      RBDataDeserialization::RBEvaluationDeserialization rb_eval_reader(rb_eval);
      rb_eval_reader.read_from_file("rb_eval.bin", /*read_error_bound_data*/ true);
#else
      rb_eval.legacy_read_offline_data_from_files("rb_data");
#endif

      // Get the parameters at which we will do a reduced basis solve
      Real online_center_x = infile("online_center_x", 0.);
      Real online_center_y = infile("online_center_y", 0.);
      RBParameters online_mu;
      online_mu.set_value("center_x", online_center_x);
      online_mu.set_value("center_y", online_center_y);
      rb_eval.set_parameters(online_mu);
      rb_eval.print_parameters();
      rb_eval.rb_solve(rb_eval.get_n_basis_functions());

      // plot the solution, if requested
      if (store_basis_functions)
        {
          // read in the data from files
          eim_rb_eval.read_in_basis_functions(eim_construction.get_explicit_system(), "eim_data");
          rb_eval.read_in_basis_functions(rb_construction, "rb_data");

          eim_construction.load_rb_solution();
          rb_construction.load_rb_solution();
#ifdef LIBMESH_HAVE_EXODUS_API
          ExodusII_IO(mesh).write_equation_systems("RB_sol.e", equation_systems);
#endif
        }
    }
}
Exemple #7
0
int main (int argc, char ** argv)
{
  START_LOG("Initialize and create cubes", "main");
  LibMeshInit init (argc, argv);

  // Create a GetPot object to parse the command line
  GetPot command_line (argc, argv);

  // Check for proper calling arguments.
  if (argc < 3)
    libmesh_error_msg("Usage:\n" << "\t " << argv[0] << " -n 15");

  // Brief message to the user regarding the program name
  // and command line arguments.
  else
    {
      libMesh::out << "Running " << argv[0];

      for (int i=1; i<argc; i++)
        libMesh::out << " " << argv[i];

      libMesh::out << std::endl << std::endl;
    }

  // This is 3D-only problem
  const unsigned int dim = 3;

  // Skip higher-dimensional examples on a lower-dimensional libMesh build
  libmesh_example_requires(dim <= LIBMESH_DIM, "3D support");

  // Read number of elements used in each cube from command line
  int ps = 10;
  if (command_line.search(1, "-n"))
    ps = command_line.next(ps);

  // Generate eight meshes that will be stitched
  SerialMesh mesh (init.comm());
  SerialMesh mesh1(init.comm());
  SerialMesh mesh2(init.comm());
  SerialMesh mesh3(init.comm());
  SerialMesh mesh4(init.comm());
  SerialMesh mesh5(init.comm());
  SerialMesh mesh6(init.comm());
  SerialMesh mesh7(init.comm());
  MeshTools::Generation::build_cube (mesh, ps, ps, ps, -1,    0,    0,  1,  0, 1, HEX8);
  MeshTools::Generation::build_cube (mesh1, ps, ps, ps,    0,  1,    0,  1,  0, 1, HEX8);
  MeshTools::Generation::build_cube (mesh2, ps, ps, ps, -1,    0, -1,    0,  0, 1, HEX8);
  MeshTools::Generation::build_cube (mesh3, ps, ps, ps,    0,  1, -1,    0,  0, 1, HEX8);
  MeshTools::Generation::build_cube (mesh4, ps, ps, ps, -1,    0,    0,  1, -1, 0, HEX8);
  MeshTools::Generation::build_cube (mesh5, ps, ps, ps,    0,  1,    0,  1, -1, 0, HEX8);
  MeshTools::Generation::build_cube (mesh6, ps, ps, ps, -1,    0, -1,    0, -1, 0, HEX8);
  MeshTools::Generation::build_cube (mesh7, ps, ps, ps,    0,  1, -1,    0, -1, 0, HEX8);

  // Generate a single unstitched reference mesh
  SerialMesh nostitch_mesh(init.comm());
  MeshTools::Generation::build_cube (nostitch_mesh, ps*2, ps*2, ps*2, -1, 1, -1, 1, -1, 1, HEX8);
  STOP_LOG("Initialize and create cubes", "main");

  START_LOG("Stitching", "main");
  // We stitch the meshes in a hierarchical way.
  mesh.stitch_meshes(mesh1, 2, 4, TOLERANCE, true, true, false, false);
  mesh2.stitch_meshes(mesh3, 2, 4, TOLERANCE, true, true, false, false);
  mesh.stitch_meshes(mesh2, 1, 3, TOLERANCE, true, true, false, false);
  mesh4.stitch_meshes(mesh5, 2, 4, TOLERANCE, true, true, false, false);
  mesh6.stitch_meshes(mesh7, 2, 4, TOLERANCE, true, true, false, false);
  mesh4.stitch_meshes(mesh6, 1, 3, TOLERANCE, true, true, false, false);
  mesh.stitch_meshes(mesh4, 0, 5, TOLERANCE, true, true, false, false);
  STOP_LOG("Stitching", "main");

  START_LOG("Initialize and solve systems", "main");
  EquationSystems equation_systems_stitch (mesh);
  assemble_and_solve(mesh, equation_systems_stitch);

  EquationSystems equation_systems_nostitch (nostitch_mesh);
  assemble_and_solve(nostitch_mesh, equation_systems_nostitch);
  STOP_LOG("Initialize and solve systems", "main");

  START_LOG("Result comparison", "main");
  ExactSolution comparison(equation_systems_stitch);
  comparison.attach_reference_solution(&equation_systems_nostitch);
  comparison.compute_error("Poisson", "u");
  Real error = comparison.l2_error("Poisson", "u");
  libmesh_assert_less(error, TOLERANCE*sqrt(TOLERANCE));
  libMesh::out << "L2 error between stitched and non-stitched cases: " << error << std::endl;
  STOP_LOG("Result comparison", "main");

  START_LOG("Output", "main");
#ifdef LIBMESH_HAVE_EXODUS_API
  ExodusII_IO(mesh).write_equation_systems("solution_stitch.exo",
                                           equation_systems_stitch);
  ExodusII_IO(nostitch_mesh).write_equation_systems("solution_nostitch.exo",
                                                    equation_systems_nostitch);
#endif // #ifdef LIBMESH_HAVE_EXODUS_API
  STOP_LOG("Output", "main");

  return 0;
}
Exemple #8
0
// Begin the main program.  Note that the first
// statement in the program throws an error if
// you are in complex number mode, since this
// example is only intended to work with real
// numbers.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  LibMeshInit init (argc, argv);

#if !defined(LIBMESH_ENABLE_AMR)
  libmesh_example_assert(false, "--enable-amr");
#elif !defined(LIBMESH_HAVE_XDR)
  // We use XDR support in our output here
  libmesh_example_assert(false, "--enable-xdr");
#elif !defined(LIBMESH_ENABLE_PERIODIC)
  libmesh_example_assert(false, "--enable-periodic");
#else

  // Our Trilinos interface does not yet support adaptive transient
  // problems
  libmesh_example_assert(libMesh::default_solver_package() == PETSC_SOLVERS, "--enable-petsc");

  // Brief message to the user regarding the program name
  // and command line arguments.

  // Use commandline parameter to specify if we are to
  // read in an initial solution or generate it ourself
  std::cout << "Usage:\n"
    <<"\t " << argv[0] << " -init_timestep 0\n"
    << "OR\n"
    <<"\t " << argv[0] << " -read_solution -init_timestep 26\n"
    << std::endl;

  std::cout << "Running: " << argv[0];

  for (int i=1; i<argc; i++)
    std::cout << " " << argv[i];

  std::cout << std::endl << std::endl;

  // Create a GetPot object to parse the command line
  GetPot command_line (argc, argv);


  // This boolean value is obtained from the command line, it is true
  // if the flag "-read_solution" is present, false otherwise.
  // It indicates whether we are going to read in
  // the mesh and solution files "saved_mesh.xda" and "saved_solution.xda"
  // or whether we are going to start from scratch by just reading
  // "mesh.xda"
  const bool read_solution   = command_line.search("-read_solution");

  // This value is also obtained from the commandline and it specifies the
  // initial value for the t_step looping variable. We must
  // distinguish between the two cases here, whether we read in the 
  // solution or we started from scratch, so that we do not overwrite the
  // gmv output files.
  unsigned int init_timestep = 0;
  
  // Search the command line for the "init_timestep" flag and if it is
  // present, set init_timestep accordingly.
  if(command_line.search("-init_timestep"))
    init_timestep = command_line.next(0);
  else
    {
      if (libMesh::processor_id() == 0)
        std::cerr << "ERROR: Initial timestep not specified\n" << std::endl;

      // This handy function will print the file name, line number,
      // and then abort.  Currrently the library does not use C++
      // exception handling.
      libmesh_error();
    }

  // This value is also obtained from the command line, and specifies
  // the number of time steps to take.
  unsigned int n_timesteps = 0;

  // Again do a search on the command line for the argument
  if(command_line.search("-n_timesteps"))
    n_timesteps = command_line.next(0);
  else
    {
      std::cout << "ERROR: Number of timesteps not specified\n" << std::endl;
      libmesh_error();
    }

  // The user can specify a different exact solution on the command
  // line, if we have an expression parser compiled in
#ifdef LIBMESH_HAVE_FPARSER
  const bool have_expression = command_line.search("-exact_solution");
#else
  const bool have_expression = false;
#endif
  if (have_expression)
    parsed_solution = new ParsedFunction<Number>(command_line.next(std::string()));

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

  // Create a new mesh.
  // ParallelMesh doesn't yet understand periodic BCs, plus
  // we still need some work on automatic parallel restarts
  SerialMesh mesh;

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

  // First we process the case where we do not read in the solution
  if(!read_solution)
    {
      MeshTools::Generation::build_square(mesh, 2, 2, 0., 2., 0., 2., QUAD4);

      // Again do a search on the command line for an argument
      unsigned int n_refinements = 5;
      if(command_line.search("-n_refinements"))
        n_refinements = command_line.next(0);

      // Uniformly refine the mesh 5 times
      if(!read_solution)
        mesh_refinement.uniformly_refine (n_refinements);

      // Print information about the mesh to the screen.
      mesh.print_info();
      
      
      // Declare the system and its variables.
      // Begin by creating a transient system
      // named "Convection-Diffusion".
      TransientLinearImplicitSystem & system = 
        equation_systems.add_system<TransientLinearImplicitSystem> 
        ("Convection-Diffusion");

      // Adds the variable "u" to "Convection-Diffusion".  "u"
      // will be approximated using first-order approximation.
      system.add_variable ("u", FIRST);

      // Give the system a pointer to the initialization function.
      system.attach_init_function (init_cd);
    }
  // Otherwise we read in the solution and mesh
  else 
    {
      // Read in the mesh stored in "saved_mesh.xda"
      mesh.read("saved_mesh.xdr");

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

      // Read in the solution stored in "saved_solution.xda"
      equation_systems.read("saved_solution.xdr", libMeshEnums::DECODE);
    }

  // Get a reference to the system so that we can attach things to it
  TransientLinearImplicitSystem & system = 
    equation_systems.get_system<TransientLinearImplicitSystem> 
    ("Convection-Diffusion");

  // Give the system a pointer to the assembly function.
  system.attach_assemble_function (assemble_cd);

  // Creating and attaching Periodic Boundaries
  DofMap & dof_map = system.get_dof_map();
  
  // Create a boundary periodic with one displaced 2.0 in the x
  // direction
  PeriodicBoundary horz(RealVectorValue(2.0, 0., 0.));

  // Connect boundary ids 3 and 1 with it
  horz.myboundary = 3;
  horz.pairedboundary = 1;

  // Add it to the PeriodicBoundaries
  dof_map.add_periodic_boundary(horz);

  
  // Create a boundary periodic with one displaced 2.0 in the y
  // direction
  PeriodicBoundary vert(RealVectorValue(0., 2.0, 0.));

  // Connect boundary ids 0 and 2 with it
  vert.myboundary = 0;
  vert.pairedboundary = 2;

  // Add it to the PeriodicBoundaries
  dof_map.add_periodic_boundary(vert);

  // Initialize the data structures for the equation system.
  if(!read_solution)
    equation_systems.init ();
  else
    equation_systems.reinit ();
 
  // Print out the H1 norm of the initialized or saved solution, for
  // verification purposes:
  Real H1norm = system.calculate_norm(*system.solution, SystemNorm(H1));

  std::cout << "Initial H1 norm = " << H1norm << std::endl << std::endl;

  // Prints information about the system to the screen.
  equation_systems.print_info();
    
  equation_systems.parameters.set<unsigned int>
    ("linear solver maximum iterations") = 250;
  equation_systems.parameters.set<Real>
    ("linear solver tolerance") = TOLERANCE;
    
  if(!read_solution)
  {
    // Write out the initial condition
#ifdef LIBMESH_HAVE_GMV
    GMVIO(mesh).write_equation_systems ("out.gmv.000",
                                        equation_systems);
#endif
#ifdef LIBMESH_HAVE_EXODUS_API
    ExodusII_IO(mesh).write_equation_systems (exodus_filename(0),
                                              equation_systems);
#endif
  }
  else
  {
    // Write out the solution that was read in
#ifdef LIBMESH_HAVE_GMV
    GMVIO(mesh).write_equation_systems ("solution_read_in.gmv",
                                        equation_systems);
#endif
#ifdef LIBMESH_HAVE_EXODUS_API
    ExodusII_IO(mesh).write_equation_systems ("solution_read_in.e",
                                        equation_systems);
#endif
  }
  

  // The Convection-Diffusion system requires that we specify
  // the flow velocity.  We will specify it as a RealVectorValue
  // data type and then use the Parameters object to pass it to
  // the assemble function.
  equation_systems.parameters.set<RealVectorValue>("velocity") = 
    RealVectorValue (0.8, 0.8);

  // The Convection-Diffusion system also requires a specified
  // diffusivity.  We use an isotropic (hence Real) value.
  equation_systems.parameters.set<Real>("diffusivity") = 0.01;
    
  // Solve the system "Convection-Diffusion".  This will be done by
  // looping over the specified time interval and calling the
  // \p solve() member at each time step.  This will assemble the
  // system and call the linear solver.

  const Real dt = 0.025;
  system.time   = init_timestep*dt;
 
  
  // Tell the MeshRefinement object about the periodic boundaries so
  // that it can get heuristics like level-one conformity and
  // unrefined island elimination right.
  mesh_refinement.set_periodic_boundaries_ptr(dof_map.get_periodic_boundaries());

  // We do 25 timesteps both before and after writing out the
  // intermediate solution
  for(unsigned int t_step=init_timestep; 
                   t_step<(init_timestep+n_timesteps); 
                   t_step++)
    {
      // Increment the time counter, set the time and the
      // time step size as parameters in the EquationSystem.
      system.time += dt;

      equation_systems.parameters.set<Real> ("time") = system.time;
      equation_systems.parameters.set<Real> ("dt")   = dt;

      // A pretty update message
      std::cout << " Solving time step ";
      
      {
        // Save flags to avoid polluting cout with custom precision values, etc.
        std::ios_base::fmtflags os_flags = std::cout.flags();

        std::cout << t_step
                  << ", time="
                  << std::setw(6)
                  << std::setprecision(3)
                  << std::setfill('0')
                  << std::left
                  << system.time
                  << "..."
                  << std::endl;

        // Restore flags
        std::cout.flags(os_flags);
      }
      
      // At this point we need to update the old
      // solution vector.  The old solution vector
      // will be the current solution vector from the
      // previous time step.  We will do this by extracting the
      // system from the \p EquationSystems object and using
      // vector assignment.  Since only \p TransientLinearImplicitSystems
      // (and systems derived from them) contain old solutions
      // we need to specify the system type when we ask for it.
      TransientLinearImplicitSystem &  system =
        equation_systems.get_system<TransientLinearImplicitSystem>("Convection-Diffusion");

      *system.old_local_solution = *system.current_local_solution;
      
      // The number of refinement steps per time step.
      unsigned int max_r_steps = 1;
      if(command_line.search("-max_r_steps"))
        max_r_steps = command_line.next(0);
      
      // A refinement loop.
      for (unsigned int r_step=0; r_step<max_r_steps+1; r_step++)
        {
          // Assemble & solve the linear system
          system.solve();

          // Print out the H1 norm, for verification purposes:
          Real H1norm = system.calculate_norm(*system.solution, SystemNorm(H1));

          std::cout << "H1 norm = " << H1norm << std::endl;
          
          // Possibly refine the mesh
          if (r_step+1 <= max_r_steps)
            {
              std::cout << "  Refining the mesh..." << std::endl;

              // The \p ErrorVector is a particular \p StatisticsVector
              // for computing error information on a finite element mesh.
              ErrorVector error;

              // The \p ErrorEstimator class interrogates a finite element
              // solution and assigns to each element a positive error value.
              // This value is used for deciding which elements to refine
              // and which to coarsen.
              //ErrorEstimator* error_estimator = new KellyErrorEstimator;
              KellyErrorEstimator error_estimator;

              // Compute the error for each active element using the provided
              // \p flux_jump indicator.  Note in general you will need to
              // provide an error estimator specifically designed for your
              // application.
              error_estimator.estimate_error (system,
                                              error);
              
              // This takes the error in \p error and decides which elements
              // will be coarsened or refined.  Any element within 20% of the
              // maximum error on any element will be refined, and any
              // element within 7% of the minimum error on any element might
              // be coarsened. Note that the elements flagged for refinement
              // will be refined, but those flagged for coarsening _might_ be
              // coarsened.
              mesh_refinement.refine_fraction() = 0.80;
              mesh_refinement.coarsen_fraction() = 0.07;
              mesh_refinement.max_h_level() = 5;
              mesh_refinement.flag_elements_by_error_fraction (error);
              
              // This call actually refines and coarsens the flagged
              // elements.
              mesh_refinement.refine_and_coarsen_elements();
              
              // This call reinitializes the \p EquationSystems object for
              // the newly refined mesh.  One of the steps in the
              // reinitialization is projecting the \p solution,
              // \p old_solution, etc... vectors from the old mesh to
              // the current one.
              equation_systems.reinit ();
            }            
        }
        
      // Again do a search on the command line for an argument
      unsigned int output_freq = 10;
      if(command_line.search("-output_freq"))
        output_freq = command_line.next(0);

      // Output every 10 timesteps to file.
      if ( (t_step+1)%output_freq == 0)
        {
          // OStringStream file_name;

#ifdef LIBMESH_HAVE_GMV
//          file_name << "out.gmv.";
//          OSSRealzeroright(file_name,3,0,t_step+1);
//
//          GMVIO(mesh).write_equation_systems (file_name.str(),
//                                              equation_systems);
#endif
#ifdef LIBMESH_HAVE_EXODUS_API
          // So... if paraview is told to open a file called out.e.{N}, it automatically tries to
          // open out.e.{N-1}, out.e.{N-2}, etc.  If we name the file something else, we can work
          // around that issue, but the right thing to do (for adaptive meshes) is to write a filename
          // with the adaptation step into a separate file.
          ExodusII_IO(mesh).write_equation_systems (exodus_filename(t_step+1),
                                                    equation_systems);
#endif
        }
    }

  if(!read_solution)
    {
      // Print out the H1 norm of the saved solution, for verification purposes:
      TransientLinearImplicitSystem& system =
	equation_systems.get_system<TransientLinearImplicitSystem>
          ("Convection-Diffusion");
      Real H1norm = system.calculate_norm(*system.solution, SystemNorm(H1));

      std::cout << "Final H1 norm = " << H1norm << std::endl << std::endl;

      mesh.write("saved_mesh.xdr");
      equation_systems.write("saved_solution.xdr", libMeshEnums::ENCODE);
#ifdef LIBMESH_HAVE_GMV
      GMVIO(mesh).write_equation_systems ("saved_solution.gmv",
                                          equation_systems);
#endif
#ifdef LIBMESH_HAVE_EXODUS_API
      ExodusII_IO(mesh).write_equation_systems ("saved_solution.e",
                                          equation_systems);
#endif
    }
#endif // #ifndef LIBMESH_ENABLE_AMR

  // We might have a parser to clean up
  delete parsed_solution;
  
  return 0;
}
Exemple #9
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;
}
Exemple #10
0
// The main program
int main (int argc, char** argv)
{
  // Initialize libraries, like in example 2.
  LibMeshInit init (argc, argv);

  // Check for proper usage.
  if (argc < 2)
    {
      if (libMesh::processor_id() == 0)
        std::cerr << "Usage: " << argv[0] << " [meshfile]"
                  << std::endl;
      
      libmesh_error();
    }
  
  // Tell the user what we are doing.
  else 
    {
      std::cout << "Running " << argv[0];
      
      for (int i=1; i<argc; i++)
        std::cout << " " << argv[i];
      
      std::cout << std::endl << std::endl;

    }

  // LasPack solvers don't work so well for this example
  // (not sure why), and Trilinos matrices don't work at all.
  // Print a warning to the user if PETSc is not in use.
  if (libMesh::default_solver_package() == LASPACK_SOLVERS)
    {
      std::cout << "WARNING! It appears you are using the\n"
                << "LasPack solvers.  This example may not converge\n"
                << "using LasPack, but should work OK with PETSc.\n"
                << "http://www.mcs.anl.gov/petsc/\n"
                << std::endl;
    }
  else if (libMesh::default_solver_package() == TRILINOS_SOLVERS)
    {
      std::cout << "WARNING! It appears you are using the\n"
                << "Trilinos solvers.  The current libMesh Epetra\n"
                << "interface does not allow sparse matrix addition,\n"
                << "as is needed in this problem.  We recommend\n"
                << "using PETSc: http://www.mcs.anl.gov/petsc/\n"
                << std::endl;
      return 0;
    }
  
  // Get the name of the mesh file
  // from the command line.
  std::string mesh_file = argv[1];
  std::cout << "Mesh file is: " << mesh_file << std::endl;

  // Skip this 3D example if libMesh was compiled as 1D or 2D-only.
  libmesh_example_assert(3 <= LIBMESH_DIM, "3D support");
  
  // Create a mesh.
  // This example directly references all mesh nodes and is
  // incompatible with ParallelMesh use.

  SerialMesh mesh;
  MeshData mesh_data(mesh);
  
  // Read the meshfile specified in the command line or
  // use the internal mesh generator to create a uniform
  // grid on an elongated cube.
  mesh.read(mesh_file, &mesh_data);
   
  // mesh.build_cube (10, 10, 40,
  //                       -1., 1.,
  //                       -1., 1.,
  //                        0., 4.,
  //                        HEX8);

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

  // The node that should be monitored.
  const unsigned int result_node = 274;

  
  // Time stepping issues
  //
  // Note that the total current time is stored as a parameter
  // in the \pEquationSystems object.
  //
  // the time step size
  const Real delta_t = .0000625;

  // The number of time steps.
  unsigned int n_time_steps = 300;
  
  // Create an equation systems object.
  EquationSystems equation_systems (mesh);

  // Declare the system and its variables.
  // Create a NewmarkSystem named "Wave"
  equation_systems.add_system<NewmarkSystem> ("Wave");

  // Use a handy reference to this system
  NewmarkSystem & t_system = equation_systems.get_system<NewmarkSystem> ("Wave");
  
  // Add the variable "p" to "Wave".   "p"
  // will be approximated using first-order approximation.
  t_system.add_variable("p", FIRST);

  // Give the system a pointer to the matrix assembly
  // function and the initial condition function defined
  // below.
  t_system.attach_assemble_function  (assemble_wave);
  t_system.attach_init_function      (apply_initial);

  // Set the time step size, and optionally the
  // Newmark parameters, so that \p NewmarkSystem can 
  // compute integration constants.  Here we simply use 
  // pass only the time step and use default values 
  // for \p alpha=.25  and \p delta=.5.
  t_system.set_newmark_parameters(delta_t);

  // Set the speed of sound and fluid density
  // as \p EquationSystems parameter,
  // so that \p assemble_wave() can access it.
  equation_systems.parameters.set<Real>("speed")          = 1000.;
  equation_systems.parameters.set<Real>("fluid density")  = 1000.;

  // Start time integration from t=0
  t_system.time = 0.;

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

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

  // A file to store the results at certain nodes.
  std::ofstream res_out("pressure_node.res");

  // get the dof_numbers for the nodes that
  // should be monitored.
  const unsigned int res_node_no = result_node;
  const Node& res_node = mesh.node(res_node_no-1);
  unsigned int dof_no = res_node.dof_number(0,0,0);

  // Assemble the time independent system matrices and rhs.
  // This function will also compute the effective system matrix
  // K~=K+a_0*M+a_1*C and apply user specified initial
  // conditions. 
  t_system.assemble();

  // Now solve for each time step.
  // For convenience, use a local buffer of the 
  // current time.  But once this time is updated,
  // also update the \p EquationSystems parameter
  // Start with t_time = 0 and write a short header
  // to the nodal result file
  res_out << "# pressure at node " << res_node_no << "\n"
          << "# time\tpressure\n"
          << t_system.time << "\t" << 0 << std::endl;


  for (unsigned int time_step=0; time_step<n_time_steps; time_step++)
    {
      // Update the time.  Both here and in the
      // \p EquationSystems object
      t_system.time += delta_t;

      // Update the rhs.
      t_system.update_rhs();

      // Impose essential boundary conditions.
      // Not that since the matrix is only assembled once,
      // the penalty parameter should be added to the matrix
      // only in the first time step.  The applied
      // boundary conditions may be time-dependent and hence
      // the rhs vector is considered in each time step. 
      if (time_step == 0)
        {
          // The local function \p fill_dirichlet_bc()
          // may also set Dirichlet boundary conditions for the
          // matrix.  When you set the flag as shown below,
          // the flag will return true.  If you want it to return
          // false, simply do not set it.
          equation_systems.parameters.set<bool>("Newmark set BC for Matrix") = true;

          fill_dirichlet_bc(equation_systems, "Wave");

          // unset the flag, so that it returns false
          equation_systems.parameters.set<bool>("Newmark set BC for Matrix") = false;
        }
      else
        fill_dirichlet_bc(equation_systems, "Wave");

      // Solve the system "Wave".
      t_system.solve();

      // After solving the system, write the solution
      // to a GMV-formatted plot file.
      // Do only for a few time steps.
      if (time_step == 30 || time_step == 60 ||
          time_step == 90 || time_step == 120 )
        {
          char buf[14];

		  if (!libMesh::on_command_line("--vtk")){
			  sprintf (buf, "out.%03d.gmv", time_step);

	          GMVIO(mesh).write_equation_systems (buf,equation_systems);

		  }else{
#ifdef LIBMESH_HAVE_VTK
			  // VTK viewers are generally not happy with two dots in a filename
			  sprintf (buf, "out_%03d.exd", time_step);

	          VTKIO(mesh).write_equation_systems (buf,equation_systems);
#endif // #ifdef LIBMESH_HAVE_VTK
		  }
        }

      // Update the p, v and a.
      t_system.update_u_v_a();

      // dof_no may not be local in parallel runs, so we may need a
      // global displacement vector
      NumericVector<Number> &displacement
        = t_system.get_vector("displacement");
      std::vector<Number> global_displacement(displacement.size());
      displacement.localize(global_displacement);

      // Write nodal results to file.  The results can then
      // be viewed with e.g. gnuplot (run gnuplot and type
      // 'plot "pressure_node.res" with lines' in the command line)
      res_out << t_system.time << "\t"
              << global_displacement[dof_no]
              << std::endl;
    }
  
  // All done.  
  return 0;
}