Real ErrorVector::median() { const unsigned int n = this->size(); if (n == 0) return 0.; // Build a StatisticsVector<ErrorVectorReal> containing // only our active entries and take its mean StatisticsVector<ErrorVectorReal> sv; sv.reserve (n); for (unsigned int i=0; i<n; i++) if(this->is_active_elem(i)) sv.push_back((*this)[i]); return sv.median(); }
int main (int argc, char** argv) { LibMeshInit init(argc, argv); PerfMon perfmon(argv[0]); unsigned int n_subdomains = 1; unsigned int n_rsteps = 0; unsigned char dim = static_cast<unsigned char>(-1); // invalid dimension double dist_fact = 0.; bool verbose = false; BoundaryMeshWriteMode write_bndry = BM_DISABLED; unsigned int convert_second_order = 0; bool addinfelems = false; bool triangulate = false; bool do_quality = false; ElemQuality quality_type = DIAGONAL; #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS InfElemBuilder::InfElemOriginValue origin_x(false, 0.); InfElemBuilder::InfElemOriginValue origin_y(false, 0.); InfElemBuilder::InfElemOriginValue origin_z(false, 0.); #endif bool x_sym=false; bool y_sym=false; bool z_sym=false; std::vector<std::string> names; std::vector<std::string> var_names; std::vector<Number> soln; process_cmd_line(argc, argv, names, n_subdomains, n_rsteps, dim, dist_fact, verbose, write_bndry, convert_second_order, triangulate, do_quality, quality_type, addinfelems, #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS origin_x, origin_y, origin_z, #endif x_sym, y_sym, z_sym); AutoPtr<Mesh> mesh_ptr; if (dim == static_cast<unsigned char>(-1)) { mesh_ptr.reset(new Mesh(init.comm())); } else { mesh_ptr.reset(new Mesh(init.comm(),dim)); } Mesh& mesh = *mesh_ptr; MeshData mesh_data(mesh); /** * Read the input mesh */ if (!names.empty()) { /* * activate the MeshData of the dim mesh, * so that it can be copied to the boundary */ if (write_bndry == BM_WITH_MESHDATA) { mesh_data.activate(); if (verbose) mesh_data.print_info(); } mesh.read(names[0]); if (verbose) { mesh.print_info(); mesh.get_boundary_info().print_summary(); } } else { libMesh::out << "No input specified." << std::endl; return 1; } #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS if(addinfelems) { if (names.size() == 3) { libMesh::out << "ERROR: Invalid combination: Building infinite elements " << std::endl << "not compatible with solution import." << std::endl; exit(1); } if (write_bndry != BM_DISABLED) { libMesh::out << "ERROR: Invalid combination: Building infinite elements " << std::endl << "not compatible with writing boundary conditions." << std::endl; exit(1); } /* * Sanity checks: -X/Y/Z can only be used, when the * corresponding coordinate is also given (using -x/y/z) */ if ((x_sym && !origin_x.first) || // claim x-symmetry, but x-coordinate of origin not given! (y_sym && !origin_y.first) || // the same for y (z_sym && !origin_z.first)) // the same for z { libMesh::out << "ERROR: When x-symmetry is requested using -X, then" << std::endl << "the option -x <coord> also has to be given." << std::endl << "This holds obviously for y and z, too." << std::endl; exit(1); } // build infinite elements InfElemBuilder(mesh).build_inf_elem(origin_x, origin_y, origin_z, x_sym, y_sym, z_sym, verbose); if (verbose) { mesh.print_info(); mesh.get_boundary_info().print_summary(); } } // sanity check else if((origin_x.first || origin_y.first || origin_z.first) || (x_sym || y_sym || z_sym)) { libMesh::out << "ERROR: -x/-y/-z/-X/-Y/-Z is only to be used when" << std::endl << "the option -a is also specified!" << std::endl; exit(1); } #endif /** * Possibly read the solution */ if (names.size() == 3) LegacyXdrIO(mesh,true).read_mgf_soln(names[2], soln, var_names); /** * Maybe Triangulate */ // if (dim == 2 && triangulate) if (triangulate) { if (verbose) libMesh::out << "...Converting to all simplices...\n"; MeshTools::Modification::all_tri(mesh); } /** * Compute Shape quality metrics */ if (do_quality) { StatisticsVector<Real> sv; sv.reserve(mesh.n_elem()); libMesh::out << "Quality type is: " << Quality::name(quality_type) << std::endl; // What are the quality bounds for this element? std::pair<Real, Real> bounds = mesh.elem(0)->qual_bounds(quality_type); libMesh::out << "Quality bounds for this element type are: (" << bounds.first << ", " << bounds.second << ") " << std::endl; MeshBase::const_element_iterator it = mesh.active_elements_begin(), end = mesh.active_elements_end(); for (; it != end; ++it) { Elem *e = *it; sv.push_back(e->quality(quality_type)); } const unsigned int n_bins = 10; libMesh::out << "Avg. shape quality: " << sv.mean() << std::endl; // Find element indices below the specified cutoff. // These might be considered "bad" elements which need refinement. std::vector<dof_id_type> bad_elts = sv.cut_below(0.8); libMesh::out << "Found " << bad_elts.size() << " of " << mesh.n_elem() << " elements below the cutoff." << std::endl; /* for (unsigned int i=0; i<bad_elts.size(); i++) libMesh::out << bad_elts[i] << " "; libMesh::out << std::endl; */ // Compute the histogram for this distribution std::vector<dof_id_type> histogram; sv.histogram(histogram, n_bins); /* for (unsigned int i=0; i<n_bins; i++) histogram[i] = histogram[i] / mesh.n_elem(); */ const bool do_matlab = true; if (do_matlab) { std::ofstream out ("histo.m"); out << "% This is a sample histogram plot for Matlab." << std::endl; out << "bin_members = [" << std::endl; for (unsigned int i=0; i<n_bins; i++) out << static_cast<Real>(histogram[i]) / static_cast<Real>(mesh.n_elem()) << std::endl; out << "];" << std::endl; std::vector<Real> bin_coords(n_bins); const Real max = *(std::max_element(sv.begin(), sv.end())); const Real min = *(std::min_element(sv.begin(), sv.end())); const Real delta = (max - min) / static_cast<Real>(n_bins); for (unsigned int i=0; i<n_bins; i++) bin_coords[i] = min + (i * delta) + delta / 2.0 ; out << "bin_coords = [" << std::endl; for (unsigned int i=0; i<n_bins; i++) out << bin_coords[i] << std::endl; out << "];" << std::endl; out << "bar(bin_coords, bin_members, 1);" << std::endl; out << "hold on" << std::endl; out << "plot (bin_coords, 0, 'kx');" << std::endl; out << "xlabel('Quality (0=Worst, 1=Best)');" << std::endl; out << "ylabel('Percentage of elements in each bin');" << std::endl; out << "axis([" << min << "," << max << ",0, max(bin_members)]);" << std::endl; out << "title('" << Quality::name(quality_type) << "');" << std::endl; } } /** * Possibly convert all linear * elements to second-order counterparts */ if (convert_second_order > 0) { bool second_order_mode = true; std:: string message = "Converting elements to second order counterparts"; if (convert_second_order == 2) { second_order_mode = false; message += ", lower version: Quad4 -> Quad8, not Quad9"; } else if (convert_second_order == 22) { second_order_mode = true; message += ", highest version: Quad4 -> Quad9"; } else libmesh_error_msg("Invalid value, convert_second_order = " << convert_second_order); if (verbose) libMesh::out << message << std::endl; mesh.all_second_order(second_order_mode); if (verbose) { mesh.print_info(); mesh.get_boundary_info().print_summary(); } } #ifdef LIBMESH_ENABLE_AMR /** * Possibly refine the mesh */ if (n_rsteps > 0) { if (verbose) libMesh::out << "Refining the mesh " << n_rsteps << " times" << std::endl; MeshRefinement mesh_refinement (mesh); mesh_refinement.uniformly_refine(n_rsteps); if (verbose) { mesh.print_info(); mesh.get_boundary_info().print_summary(); } } /** * Possibly distort the mesh */ if (dist_fact > 0.) { libMesh::out << "Distoring the mesh by a factor of " << dist_fact << std::endl; MeshTools::Modification::distort(mesh,dist_fact); }; /* char filechar[81]; sprintf(filechar,"%s-%04d.plt", "out", 0); std::string oname(filechar); mesh.write(oname); for (unsigned int step=0; step<100; step++) { // const Real x = .5 + .25*cos((((Real) step)/100.)*3.1415927); // const Real y = .5 + .25*sin((((Real) step)/100.)*3.1415927); const Real x = 2.5*cos((((Real) step)/100.)*3.1415927); const Real y = 2.5*sin((((Real) step)/100.)*3.1415927); const Point p(x,y); for (unsigned int e=0; e<mesh.n_elem(); e++) if (mesh.elem(e)->active()) mesh.elem(e)->set_refinement_flag() = -1; for (unsigned int e=0; e<mesh.n_elem(); e++) if (mesh.elem(e)->active()) { const Point diff = mesh.elem(e)->centroid(mesh) - p; if (diff.size() < .5) { if (mesh.elem(e)->level() < 4) mesh.elem(e)->set_refinement_flag() = 1; else if (mesh.elem(e)->level() == 4) mesh.elem(e)->set_refinement_flag() = 0; } } mesh.mesh_refinement.refine_and_coarsen_elements(); char filechar[81]; sprintf(filechar,"%s-%04d.plt", "out", step+1); std::string oname(filechar); mesh.write(oname); } */ #endif // /** // * Possibly partition the mesh // */ if (n_subdomains > 1) mesh.partition(n_subdomains); /** * Possibly write the mesh */ { if (names.size() >= 2) { /* * When the mesh got refined, it is likely that * the user does _not_ want to write also * the coarse elements, but only the active ones. * Use Mesh::create_submesh() to create a mesh * of only active elements, and then write _this_ * new mesh. */ if (n_rsteps > 0) { if (verbose) libMesh::out << " Mesh got refined, will write only _active_ elements." << std::endl; Mesh new_mesh (init.comm(), mesh.mesh_dimension()); construct_mesh_of_active_elements(new_mesh, mesh); // now write the new_mesh if (names.size() == 2) new_mesh.write(names[1]); else if (names.size() == 3) new_mesh.write(names[1], soln, var_names); else libmesh_error_msg("Invalid names.size() = " << names.size()); } else { if (names.size() == 2) mesh.write(names[1]); else if (names.size() == 3) mesh.write(names[1], soln, var_names); else libmesh_error_msg("Invalid names.size() = " << names.size()); } /** * Possibly write the BCs */ if (write_bndry != BM_DISABLED) { BoundaryMesh boundary_mesh (mesh.comm(), cast_int<unsigned char>(mesh.mesh_dimension()-1)); MeshData boundary_mesh_data (boundary_mesh); std::string boundary_name = "bndry_"; boundary_name += names[1]; if (write_bndry == BM_MESH_ONLY) mesh.get_boundary_info().sync(boundary_mesh); else if (write_bndry == BM_WITH_MESHDATA) mesh.get_boundary_info().sync(boundary_mesh, &boundary_mesh_data, &mesh_data); else libmesh_error_msg("Invalid value write_bndry = " << write_bndry); if (names.size() == 2) boundary_mesh.write(boundary_name); else if (names.size() == 3) boundary_mesh.write(boundary_name, soln, var_names); } } }; /* libMesh::out << "Infinite loop, look at memory footprint" << std::endl; for (;;) ; */ return 0; }
int main (int argc, char ** argv) { LibMeshInit init(argc, argv); unsigned int n_subdomains = 1; unsigned int n_rsteps = 0; double dist_fact = 0.; bool verbose = false; BoundaryMeshWriteMode write_bndry = BM_DISABLED; bool convert_first_order = false; unsigned int convert_second_order = 0; bool triangulate = false; bool do_quality = false; ElemQuality quality_type = DIAGONAL; #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS bool addinfelems = false; InfElemBuilder::InfElemOriginValue origin_x(false, 0.); InfElemBuilder::InfElemOriginValue origin_y(false, 0.); InfElemBuilder::InfElemOriginValue origin_z(false, 0.); bool x_sym=false; bool y_sym=false; bool z_sym=false; #endif std::vector<std::string> names; std::vector<std::string> var_names; std::vector<Number> soln; // Check for minimum number of command line args if (argc < 3) usage(std::string(argv[0])); // Create a GetPot object to parse the command line GetPot command_line (argc, argv); // Print usage and exit immediately if user asked for help. if (command_line.search(2, "-h", "-?")) usage(argv[0]); // Input file name if (command_line.search(1, "-i")) { std::string tmp; tmp = command_line.next(tmp); if (names.empty()) names.push_back(tmp); else libmesh_error_msg("ERROR: Input name must precede output name!"); } // Output file name if (command_line.search(1, "-o")) { std::string tmp; tmp = command_line.next(tmp); if (!names.empty()) names.push_back(tmp); else libmesh_error_msg("ERROR: Input name must precede output name!"); } // Get the mesh distortion factor if (command_line.search(1, "-D")) dist_fact = command_line.next(dist_fact); // Number of refinements if (command_line.search(1, "-r")) { int tmp; tmp = command_line.next(tmp); n_rsteps = cast_int<unsigned int>(tmp); } // Number of subdomains for partitioning if (command_line.search(1, "-p")) { int tmp; tmp = command_line.next(tmp); n_subdomains = cast_int<unsigned int>(tmp); } // Should we call all_tri()? if (command_line.search(1, "-t")) triangulate = true; // Should we calculate element quality? if (command_line.search(1, "-q")) { do_quality = true; std::string tmp; tmp = command_line.next(tmp); if (tmp != "") quality_type = Utility::string_to_enum<ElemQuality>(tmp); } // Should we be verbose? if (command_line.search(1, "-v")) verbose = true; // Should we write the boundary? if (command_line.search(1, "-b")) write_bndry = BM_MESH_ONLY; // Should we convert all elements to 1st order? if (command_line.search(1, "-1")) convert_first_order = true; // Should we convert all elements to 2nd order? if (command_line.search(1, "-2")) convert_second_order = 2; // Should we convert all elements to "full" 2nd order? if (command_line.search(1, "-3")) convert_second_order = 22; #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS // Add infinte elements if (command_line.search(1, "-a")) addinfelems = true; // Specify origin x coordinate if (command_line.search(1, "-x")) { origin_x.first = true; origin_x.second = command_line.next(origin_x.second); } // Specify origin y coordinate if (command_line.search(1, "-y")) { origin_y.first = true; origin_y.second = command_line.next(origin_y.second); } // Specify origin z coordinate if (command_line.search(1, "-z")) { origin_z.first = true; origin_z.second = command_line.next(origin_z.second); } // Symmetries if (command_line.search(1, "-X")) x_sym = true; if (command_line.search(1, "-Y")) y_sym = true; if (command_line.search(1, "-Z")) z_sym = true; #endif // LIBMESH_ENABLE_INFINITE_ELEMENTS // Read the input mesh Mesh mesh(init.comm()); if (!names.empty()) { mesh.read(names[0]); if (verbose) { mesh.print_info(); mesh.get_boundary_info().print_summary(); } } else { libMesh::out << "No input specified." << std::endl; return 1; } #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS if (addinfelems) { if (names.size() == 3) libmesh_error_msg("ERROR: Invalid combination: Building infinite elements\n" << "not compatible with solution import."); if (write_bndry != BM_DISABLED) libmesh_error_msg("ERROR: Invalid combination: Building infinite elements\n" << "not compatible with writing boundary conditions."); // Sanity checks: -X/Y/Z can only be used, when the // corresponding coordinate is also given (using -x/y/z) if ((x_sym && !origin_x.first) || // claim x-symmetry, but x-coordinate of origin not given! (y_sym && !origin_y.first) || // the same for y (z_sym && !origin_z.first)) // the same for z libmesh_error_msg("ERROR: When x-symmetry is requested using -X, then\n" << "the option -x <coord> also has to be given.\n" << "This holds obviously for y and z, too."); // build infinite elements InfElemBuilder(mesh).build_inf_elem(origin_x, origin_y, origin_z, x_sym, y_sym, z_sym, verbose); if (verbose) { mesh.print_info(); mesh.get_boundary_info().print_summary(); } } // sanity check else if ((origin_x.first || origin_y.first || origin_z.first) || (x_sym || y_sym || z_sym)) libmesh_error_msg("ERROR: -x/-y/-z/-X/-Y/-Z is only to be used when\n" << "the option -a is also specified!"); #endif // Maybe Triangulate if (triangulate) { if (verbose) libMesh::out << "...Converting to all simplices...\n"; MeshTools::Modification::all_tri(mesh); } // Compute Shape quality metrics if (do_quality) { StatisticsVector<Real> sv; sv.reserve(mesh.n_elem()); libMesh::out << "Quality type is: " << Quality::name(quality_type) << std::endl; // What are the quality bounds for this element? std::pair<Real, Real> bounds = mesh.elem_ref(0).qual_bounds(quality_type); libMesh::out << "Quality bounds for this element type are: (" << bounds.first << ", " << bounds.second << ") " << std::endl; for (const auto & elem : mesh.active_element_ptr_range()) sv.push_back(elem->quality(quality_type)); const unsigned int n_bins = 10; libMesh::out << "Avg. shape quality: " << sv.mean() << std::endl; // Find element indices below the specified cutoff. // These might be considered "bad" elements which need refinement. std::vector<dof_id_type> bad_elts = sv.cut_below(0.8); libMesh::out << "Found " << bad_elts.size() << " of " << mesh.n_elem() << " elements below the cutoff." << std::endl; // Compute the histogram for this distribution std::vector<dof_id_type> histogram; sv.histogram(histogram, n_bins); const bool do_matlab = true; if (do_matlab) { std::ofstream out ("histo.m"); out << "% This is a sample histogram plot for Matlab." << std::endl; out << "bin_members = [" << std::endl; for (unsigned int i=0; i<n_bins; i++) out << static_cast<Real>(histogram[i]) / static_cast<Real>(mesh.n_elem()) << std::endl; out << "];" << std::endl; std::vector<Real> bin_coords(n_bins); const Real max = *(std::max_element(sv.begin(), sv.end())); const Real min = *(std::min_element(sv.begin(), sv.end())); const Real delta = (max - min) / static_cast<Real>(n_bins); for (unsigned int i=0; i<n_bins; i++) bin_coords[i] = min + (i * delta) + delta / 2.0 ; out << "bin_coords = [" << std::endl; for (unsigned int i=0; i<n_bins; i++) out << bin_coords[i] << std::endl; out << "];" << std::endl; out << "bar(bin_coords, bin_members, 1);" << std::endl; out << "hold on" << std::endl; out << "plot (bin_coords, 0, 'kx');" << std::endl; out << "xlabel('Quality (0=Worst, 1=Best)');" << std::endl; out << "ylabel('Percentage of elements in each bin');" << std::endl; out << "axis([" << min << "," << max << ",0, max(bin_members)]);" << std::endl; out << "title('" << Quality::name(quality_type) << "');" << std::endl; } } // Possibly convert all linear elements to second-order // counterparts if (convert_first_order) { if (verbose) libMesh::out << "Converting elements to first order counterparts\n"; mesh.all_first_order(); if (verbose) { mesh.print_info(); mesh.get_boundary_info().print_summary(); } } // Possibly convert all linear elements to second-order counterparts if (convert_second_order > 0) { bool second_order_mode = true; std:: string message = "Converting elements to second order counterparts"; if (convert_second_order == 2) { second_order_mode = false; message += ", lower version: Quad4 -> Quad8, not Quad9"; } else if (convert_second_order == 22) { second_order_mode = true; message += ", highest version: Quad4 -> Quad9"; } else libmesh_error_msg("Invalid value, convert_second_order = " << convert_second_order); if (verbose) libMesh::out << message << std::endl; mesh.all_second_order(second_order_mode); if (verbose) { mesh.print_info(); mesh.get_boundary_info().print_summary(); } } #ifdef LIBMESH_ENABLE_AMR // Possibly refine the mesh if (n_rsteps > 0) { if (verbose) libMesh::out << "Refining the mesh " << n_rsteps << " times" << std::endl; MeshRefinement mesh_refinement (mesh); mesh_refinement.uniformly_refine(n_rsteps); if (verbose) { mesh.print_info(); mesh.get_boundary_info().print_summary(); } } // Possibly distort the mesh if (dist_fact > 0.) { libMesh::out << "Distorting the mesh by a factor of " << dist_fact << std::endl; MeshTools::Modification::distort(mesh,dist_fact); } #endif // Possibly partition the mesh if (n_subdomains > 1) mesh.partition(n_subdomains); // Possibly write the mesh if (names.size() >= 2) { // When the mesh got refined, it is likely that // the user does _not_ want to write also // the coarse elements, but only the active ones. // Use Mesh::create_submesh() to create a mesh // of only active elements, and then write _this_ // new mesh. if (n_rsteps > 0) { if (verbose) libMesh::out << " Mesh got refined, will write only _active_ elements." << std::endl; Mesh new_mesh (init.comm(), cast_int<unsigned char>(mesh.mesh_dimension())); mesh.create_submesh (new_mesh, mesh.active_elements_begin(), mesh.active_elements_end()); // now write the new_mesh if (names.size() == 2) new_mesh.write(names[1]); else if (names.size() == 3) new_mesh.write(names[1], soln, var_names); else libmesh_error_msg("Invalid names.size() = " << names.size()); } else { if (names.size() == 2) mesh.write(names[1]); else if (names.size() == 3) mesh.write(names[1], soln, var_names); else libmesh_error_msg("Invalid names.size() = " << names.size()); } // Possibly write the BCs if (write_bndry != BM_DISABLED) { BoundaryMesh boundary_mesh (mesh.comm(), cast_int<unsigned char>(mesh.mesh_dimension()-1)); std::string boundary_name = "bndry_"; boundary_name += names[1]; if (write_bndry == BM_MESH_ONLY) mesh.get_boundary_info().sync(boundary_mesh); else libmesh_error_msg("Invalid value write_bndry = " << write_bndry); if (names.size() == 2) boundary_mesh.write(boundary_name); else if (names.size() == 3) boundary_mesh.write(boundary_name, soln, var_names); } } return 0; }