// Code to save node positions, perturb the mesh, and ensure the correct nodes moved. void perturb_and_check(ReplicatedMesh & mesh) { // Record node positions ahead of time to make sure the correct // ones are moved by distort. std::unordered_map<dof_id_type, Point> pts_before; for (const auto & node : mesh.node_ptr_range()) pts_before[node->id()] = *node; std::unordered_set<dof_id_type> boundary_node_ids = MeshTools::find_boundary_nodes (mesh); MeshTools::Modification::distort(mesh, /*factor=*/0.1, /*perturb_boundary=*/false); // Make sure the boundary nodes are not perturbed, and the // other nodes are. for (const auto & node : mesh.node_ptr_range()) { bool equal = node->absolute_fuzzy_equals(pts_before[node->id()]); CPPUNIT_ASSERT(boundary_node_ids.count(node->id()) ? equal : !equal); } }
// Begin the main program. int main (int argc, char ** argv) { // Initialize libMesh. LibMeshInit init (argc, argv); // This example requires a linear solver package. libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE, "--enable-petsc, --enable-trilinos, or --enable-eigen"); // 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 DistributedMesh yet. ReplicatedMesh 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 afterward. 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 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).norm_sq(); for (unsigned int nid=1; nid<mesh.n_nodes(); ++nid) { const Real dist_sq = mesh.point(nid).norm_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. libMesh::out << "z-displacement of the center point: " << w << std::endl; libMesh::out << "Analytic solution for pure bending: " << w_analytic << std::endl; #endif // #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES #endif // #ifdef LIBMESH_ENABLE_AMR // All done. return 0; }
int main (int argc, char ** argv) { START_LOG("Initialize and create cubes", "main"); LibMeshInit init (argc, argv); // This example requires a linear solver package. libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE, "--enable-petsc, --enable-trilinos, or --enable-eigen"); // 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 ReplicatedMesh mesh (init.comm()); ReplicatedMesh mesh1(init.comm()); ReplicatedMesh mesh2(init.comm()); ReplicatedMesh mesh3(init.comm()); ReplicatedMesh mesh4(init.comm()); ReplicatedMesh mesh5(init.comm()); ReplicatedMesh mesh6(init.comm()); ReplicatedMesh 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 ReplicatedMesh 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; }
int main (int argc, char ** argv) { // Initialize libMesh. LibMeshInit init (argc, argv); // This example requires a linear solver package. libmesh_example_requires(libMesh::default_solver_package() != INVALID_SOLVER_PACKAGE, "--enable-petsc, --enable-trilinos, or --enable-eigen"); #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 ReplicatedMesh here // due to a reduced_basis regression with DistributedMesh ReplicatedMesh 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 } } }