mirror of https://github.com/CGAL/cgal
681 lines
22 KiB
C++
681 lines
22 KiB
C++
#include "benchmark_config.h"
|
|
#include "benchmark_xml.h"
|
|
#include "mesh_quality.h"
|
|
|
|
std::string XML_perf_data::default_filename;
|
|
|
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
|
|
|
#include <CGAL/Mesh_triangulation_3.h>
|
|
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
|
|
#include <CGAL/Mesh_criteria_3.h>
|
|
#include <CGAL/Labeled_mesh_domain_3.h>
|
|
#include <CGAL/Mesh_polyhedron_3.h>
|
|
#include <CGAL/Polyhedral_mesh_domain_3.h>
|
|
#include <CGAL/Polyhedral_mesh_domain_with_features_3.h>
|
|
#include <CGAL/Mesh_domain_with_polyline_features_3.h>
|
|
#include <CGAL/make_mesh_3.h>
|
|
#include <CGAL/refine_mesh_3.h>
|
|
|
|
#include <CGAL/boost/graph/IO/polygon_mesh_io.h>
|
|
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
|
|
|
|
#ifdef CGAL_LINKED_WITH_TBB
|
|
# include <tbb/task_arena.h>
|
|
# define TBB_PREVIEW_GLOBAL_CONTROL 1
|
|
# include <tbb/global_control.h>
|
|
#endif
|
|
|
|
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <signal.h>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
namespace PMP = CGAL::Polygon_mesh_processing;
|
|
|
|
// basic types from kernel
|
|
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
|
typedef K::FT FT;
|
|
typedef K::Point_3 Point;
|
|
typedef K::Sphere_3 Sphere;
|
|
|
|
// To avoid verbose function and named parameters call
|
|
using namespace CGAL::parameters;
|
|
|
|
#include "implicit_functions.h"
|
|
|
|
std::string get_output_filename(const std::string& input_name)
|
|
{
|
|
std::string filename = std::string(input_name);
|
|
filename = filename.substr(filename.find_last_of("/") + 1, filename.length() - 1);
|
|
filename = filename.substr(0, filename.find_last_of("."));
|
|
return filename;
|
|
}
|
|
|
|
std::string get_technique()
|
|
{
|
|
std::string tech;
|
|
#ifdef CGAL_CONCURRENT_MESH_3
|
|
|
|
tech += "Task-scheduler (auto";
|
|
# ifdef CGAL_MESH_3_LOAD_BASED_WORKSHARING
|
|
tech += ", load-based worksharing";
|
|
#endif
|
|
tech += ")";
|
|
|
|
#else // !CGAL_CONCURRENT_MESH_3
|
|
|
|
tech += "Sequential ";
|
|
# if defined(CGAL_MESH_3_USE_LAZY_UNSORTED_REFINEMENT_QUEUE)
|
|
# ifdef CGAL_MESH_3_IF_UNSORTED_QUEUE_JUST_SORT_AFTER_SCAN
|
|
tech += "(sort after scan only";
|
|
# else
|
|
tech += "(unsorted";
|
|
# endif
|
|
# elif defined(CGAL_MESH_3_USE_LAZY_SORTED_REFINEMENT_QUEUE)
|
|
tech += "(sorted";
|
|
# else
|
|
tech += "(NOT LAZY, sorted";
|
|
# endif
|
|
|
|
#ifdef CGAL_SEQUENTIAL_MESH_3_ADD_OUTSIDE_POINTS_ON_A_FAR_SPHERE
|
|
tech += ", points on far sphere)";
|
|
#else
|
|
tech += ")";
|
|
#endif
|
|
|
|
#endif // CGAL_CONCURRENT_MESH_3
|
|
|
|
return tech;
|
|
}
|
|
|
|
void display_info(int num_threads)
|
|
{
|
|
std::cout << get_technique() << std::endl;
|
|
|
|
#ifdef CGAL_CONCURRENT_MESH_3
|
|
|
|
if(num_threads != -1)
|
|
std::cout << "Num threads = " << num_threads << std::endl;
|
|
else
|
|
std::cout << "Num threads = AUTO" << std::endl;
|
|
|
|
#else // !CGAL_CONCURRENT_MESH_3
|
|
|
|
# ifdef CGAL_MESH_3_INITIAL_POINTS_NO_RANDOM_SHOOTING
|
|
std::cout << "NO random shooting)" << std::endl;
|
|
# else
|
|
std::cout << "WITH random shooting)" << std::endl;
|
|
# endif
|
|
|
|
#endif // CGAL_CONCURRENT_MESH_3
|
|
}
|
|
|
|
void xml_perf_set_technique()
|
|
{
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Technique", get_technique());
|
|
}
|
|
|
|
#ifdef CGAL_MESH_3_IMPLICIT_WITH_FEATURES
|
|
// To add a crease (feature) to some implicit function
|
|
typedef std::vector<Point> Crease;
|
|
typedef std::list<Crease> Creases;
|
|
|
|
void add_crease(const Point& a,
|
|
const Point& b,
|
|
Creases& creases)
|
|
{
|
|
Crease crease;
|
|
crease.push_back(a);
|
|
crease.push_back(b);
|
|
creases.push_back(crease);
|
|
}
|
|
#endif
|
|
|
|
enum Exit_code
|
|
{
|
|
// Success
|
|
VALID_OUTPUT = 0,
|
|
|
|
// Failure
|
|
INPUT_IS_INVALID = 1,
|
|
OUTPUT_IS_INVALID = 2
|
|
};
|
|
|
|
// the call to Mesh_3 happens here
|
|
template <typename C3t3, typename Domain>
|
|
Exit_code make_mesh(const Domain& domain,
|
|
const CGAL::Mesh_criteria_3<typename C3t3::Triangulation>& criteria,
|
|
const std::string& output_filename)
|
|
{
|
|
#ifdef _DEBUG
|
|
double timelimit = 10;
|
|
double sliverbound = 2;
|
|
#else
|
|
double timelimit = 0; // when making charts, we run this executable a timeout
|
|
double sliverbound = 2;
|
|
#endif
|
|
|
|
CGAL::Real_timer t;
|
|
t.start();
|
|
|
|
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain
|
|
, criteria
|
|
# ifdef CGAL_MESH_3_BENCHMARK_LLOYD
|
|
, lloyd(time_limit=timelimit)
|
|
# else
|
|
, no_lloyd()
|
|
# endif
|
|
# ifdef CGAL_MESH_3_BENCHMARK_ODT
|
|
, odt(time_limit=timelimit)
|
|
# else
|
|
, no_odt()
|
|
#endif
|
|
# ifdef CGAL_MESH_3_BENCHMARK_PERTURB
|
|
, perturb(time_limit = timelimit,
|
|
sliver_bound = sliverbound)
|
|
# else
|
|
, no_perturb()
|
|
#endif
|
|
#ifdef CGAL_MESH_3_BENCHMARK_EXUDE
|
|
, exude(time_limit = timelimit,
|
|
sliver_bound = sliverbound)
|
|
#else
|
|
, no_exude()
|
|
#endif
|
|
#ifdef CGAL_MESH_3_MANIFOLD
|
|
, manifold()
|
|
#else
|
|
, non_manifold()
|
|
#endif
|
|
);
|
|
t.stop();
|
|
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("V", c3t3.triangulation().number_of_vertices());
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("F", c3t3.number_of_facets_in_complex());
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("C", c3t3.number_of_cells_in_complex());
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Mem", CGAL::Memory_sizer().virtual_size() >> 20);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Total_time", t.time());
|
|
|
|
#ifdef CGAL_MESH_3_BENCHMARK_EXPORT_TO_MAYA
|
|
std::cout << "Exporting to " << output_filename + ".maya (Maya)... ";
|
|
std::ofstream out_maya(output_filename + ".maya");
|
|
c3t3.output_to_maya(out_maya, true);
|
|
std::cout << "done." << std::endl;
|
|
#endif
|
|
|
|
#ifdef CGAL_MESH_3_BENCHMARK_EXPORT_TO_MESH
|
|
std::cout << "Exporting to " << output_filename + ".mesh (Medit)... ";
|
|
// std::cout << "std::filesystem::current_path() = " << std::filesystem::current_path() << std::endl;
|
|
std::ofstream out_medit(output_filename + ".mesh");
|
|
c3t3.output_to_medit(out_medit, true);
|
|
std::cout << "done." << std::endl;
|
|
#endif
|
|
|
|
if(!c3t3.triangulation().is_valid() || !c3t3.is_valid())
|
|
{
|
|
std::cerr << "Error: invalid output" << std::endl;
|
|
return OUTPUT_IS_INVALID;
|
|
}
|
|
|
|
if(c3t3.number_of_facets_in_complex() == 0)
|
|
{
|
|
std::cerr << "Error: no facets in output" << std::endl;
|
|
return OUTPUT_IS_INVALID;
|
|
}
|
|
|
|
if(c3t3.number_of_cells_in_complex() == 0)
|
|
{
|
|
std::cerr << "Error: no cells in output" << std::endl;
|
|
return OUTPUT_IS_INVALID;
|
|
}
|
|
|
|
generate_quality_metrics(c3t3);
|
|
|
|
return VALID_OUTPUT;
|
|
}
|
|
|
|
template <typename C3t3, typename Domain>
|
|
Exit_code make_mesh(const Domain& domain,
|
|
double facet_sizing, double facet_approx, double facet_ang,
|
|
double cell_sizing, double cell_shape,
|
|
const std::string& output_filename)
|
|
{
|
|
typedef CGAL::Mesh_criteria_3<typename C3t3::Triangulation> Mesh_criteria;
|
|
|
|
const CGAL::Bbox_3 bbox = domain.bbox();
|
|
|
|
const double diag_length = std::sqrt(CGAL::square(bbox.xmax() - bbox.xmin()) +
|
|
CGAL::square(bbox.ymax() - bbox.ymin()) +
|
|
CGAL::square(bbox.zmax() - bbox.zmin()));
|
|
|
|
if(USE_RELATIVE_CRITERIA_VALUES)
|
|
{
|
|
facet_sizing = diag_length / facet_sizing;
|
|
facet_approx = diag_length / facet_approx;
|
|
cell_sizing = diag_length / cell_sizing;
|
|
}
|
|
|
|
Mesh_criteria criteria(edge_size = facet_sizing,
|
|
facet_angle = facet_ang,
|
|
facet_size = facet_sizing,
|
|
facet_distance = facet_approx,
|
|
cell_size = cell_sizing,
|
|
cell_radius_edge_ratio = cell_shape);
|
|
|
|
std::cout << " * edge max size: " << facet_sizing << std::endl
|
|
<< " * facet max size: " << facet_sizing << std::endl
|
|
<< " * facet approx error: " << facet_approx << std::endl
|
|
<< " * facet min angle: " << facet_ang << std::endl
|
|
<< " * cell max size: " << cell_sizing << std::endl
|
|
<< " * cell shape (radius-edge): " << cell_shape << std::endl;
|
|
|
|
return make_mesh<C3t3>(domain, criteria, output_filename);
|
|
}
|
|
|
|
Exit_code make_mesh_polyhedron(const std::string& input_filename,
|
|
double facet_sizing, double facet_approx, double facet_angle,
|
|
double cell_sizing, double cell_shape)
|
|
{
|
|
std::cout << "make_mesh_polyhedron(" << input_filename << ")" << std::endl;
|
|
|
|
// Domain
|
|
#ifdef CGAL_MESH_3_POLYHEDRON_WITH_FEATURES
|
|
typedef CGAL::Mesh_polyhedron_3<K>::type Polyhedron;
|
|
typedef CGAL::Polyhedral_mesh_domain_with_features_3<K> Mesh_domain;
|
|
#else
|
|
typedef CGAL::Polyhedron_3<K> Polyhedron;
|
|
typedef CGAL::Polyhedral_mesh_domain_3<Polyhedron, K> Mesh_domain;
|
|
#endif
|
|
|
|
// Triangulation
|
|
#ifdef CGAL_CONCURRENT_MESH_3
|
|
typedef CGAL::Mesh_triangulation_3<Mesh_domain,
|
|
CGAL::Kernel_traits<Mesh_domain>::Kernel,
|
|
CGAL::Parallel_tag>::type Tr;
|
|
#else
|
|
typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
|
|
#endif
|
|
|
|
// C3t3
|
|
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
|
|
|
|
// Create input polyhedron
|
|
Polyhedron polyhedron;
|
|
if(!CGAL::IO::read_polygon_mesh(input_filename, polyhedron))
|
|
{
|
|
std::cerr << "Error: Could not read '" << input_filename << "'" << std::endl;
|
|
return INPUT_IS_INVALID;
|
|
}
|
|
|
|
if(is_empty(polyhedron) ||
|
|
!is_triangle_mesh(polyhedron) ||
|
|
!is_closed(polyhedron) ||
|
|
PMP::does_self_intersect(polyhedron))
|
|
{
|
|
std::cerr << "Error: input has defects" << std::endl;
|
|
return INPUT_IS_INVALID;
|
|
}
|
|
|
|
std::cout << "Building AABB tree... " << std::endl;
|
|
// Create domain
|
|
Mesh_domain domain(polyhedron);
|
|
std::cout << "done." << std::endl;
|
|
|
|
#ifdef CGAL_MESH_3_POLYHEDRON_WITH_FEATURES
|
|
std::cout << "Detecting features..." << std::endl;
|
|
domain.detect_features();
|
|
std::cout << "done." << std::endl;
|
|
#endif
|
|
|
|
return make_mesh<C3t3>(domain,
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape,
|
|
get_output_filename(input_filename));
|
|
}
|
|
|
|
Exit_code make_mesh_3D_images(const std::string& input_filename,
|
|
double facet_sizing, double facet_approx, double facet_angle,
|
|
double cell_sizing, double cell_shape)
|
|
{
|
|
std::cout << "make_mesh_3D_images(" << input_filename << ")" << std::endl;
|
|
|
|
// Domain
|
|
typedef CGAL::Labeled_mesh_domain_3<K> Mesh_domain;
|
|
|
|
// Triangulation
|
|
#ifdef CGAL_CONCURRENT_MESH_3
|
|
typedef CGAL::Mesh_triangulation_3<Mesh_domain,
|
|
CGAL::Kernel_traits<Mesh_domain>::Kernel,
|
|
CGAL::Parallel_tag>::type Tr;
|
|
#else
|
|
typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
|
|
#endif
|
|
|
|
// C3t3
|
|
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
|
|
|
|
// Load image
|
|
CGAL::Image_3 image;
|
|
image.read(input_filename.c_str());
|
|
|
|
// Create domain
|
|
Mesh_domain domain = Mesh_domain::create_labeled_image_mesh_domain(image);
|
|
std::cout << "done." << std::endl;
|
|
|
|
return make_mesh<C3t3>(domain,
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape,
|
|
get_output_filename(input_filename));
|
|
}
|
|
|
|
template <class ImplicitFunction>
|
|
Exit_code make_mesh_implicit(const std::string& function_name,
|
|
ImplicitFunction func,
|
|
double facet_sizing, double facet_approx, double facet_angle,
|
|
double cell_sizing, double cell_shape)
|
|
{
|
|
std::cout << "make_mesh_implicit(" << function_name << ")" << std::endl;
|
|
|
|
// Domain
|
|
#ifdef CGAL_MESH_3_IMPLICIT_WITH_FEATURES
|
|
typedef CGAL::Labeled_mesh_domain_3<K> Implicit_domain;
|
|
typedef CGAL::Mesh_domain_with_polyline_features_3<Implicit_domain> Mesh_domain;
|
|
#else
|
|
typedef CGAL::Labeled_mesh_domain_3<K> Mesh_domain;
|
|
#endif
|
|
|
|
// Triangulation
|
|
#ifdef CGAL_CONCURRENT_MESH_3
|
|
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain,
|
|
typename CGAL::Kernel_traits<Mesh_domain>::Kernel,
|
|
CGAL::Parallel_tag>::type Tr;
|
|
#else
|
|
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
|
|
#endif
|
|
|
|
// C3t3
|
|
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
|
|
|
|
// Create domain
|
|
Sphere bounding_sphere(CGAL::ORIGIN, 10.0 * 10.0);
|
|
|
|
namespace p = CGAL::parameters;
|
|
Mesh_domain domain = Mesh_domain::create_implicit_mesh_domain(p::function = func,
|
|
p::bounding_object = bounding_sphere
|
|
/*, p::relative_error_bound = 1e-7*/);
|
|
|
|
#ifdef CGAL_MESH_3_IMPLICIT_WITH_FEATURES
|
|
// Add 12 feature creases
|
|
Creases creases;
|
|
Point p1(-1.0, -1.0, -1.0);
|
|
Point p2(-1.0, -1.0, 1.0);
|
|
Point p3(-1.0, 1.0, 1.0);
|
|
Point p4(-1.0, 1.0, -1.0);
|
|
Point p5( 1.0, -1.0, -1.0);
|
|
Point p6( 1.0, -1.0, 1.0);
|
|
Point p7( 1.0, 1.0, 1.0);
|
|
Point p8( 1.0, 1.0, -1.0);
|
|
|
|
add_crease(p1, p2, creases);
|
|
add_crease(p2, p3, creases);
|
|
add_crease(p3, p4, creases);
|
|
add_crease(p4, p1, creases);
|
|
|
|
add_crease(p5, p6, creases);
|
|
add_crease(p6, p7, creases);
|
|
add_crease(p7, p8, creases);
|
|
add_crease(p8, p5, creases);
|
|
|
|
add_crease(p5, p1, creases);
|
|
add_crease(p6, p2, creases);
|
|
add_crease(p7, p3, creases);
|
|
add_crease(p8, p4, creases);
|
|
|
|
domain.add_features(creases.begin(), creases.end());
|
|
#endif
|
|
|
|
return make_mesh<C3t3>(domain,
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape,
|
|
function_name);
|
|
}
|
|
|
|
// logs the parameters, and dispatch to polyhedral, implicit or image domain
|
|
Exit_code run(const std::string& input,
|
|
double facet_approx, double facet_sizing, double facet_angle,
|
|
double cell_sizing, double cell_shape,
|
|
int num_iteration)
|
|
{
|
|
std::string domain = input;
|
|
size_t slash_index = domain.find_last_of('/');
|
|
if(slash_index == std::string::npos)
|
|
slash_index = domain.find_last_of('\\');
|
|
if(slash_index == std::string::npos)
|
|
slash_index = 0;
|
|
else
|
|
++slash_index;
|
|
|
|
domain = domain.substr(slash_index, domain.find_last_of('.') - slash_index);
|
|
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Domain", domain);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Facet_size", facet_sizing);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Facet_approx", facet_approx);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Facet_angle", facet_angle);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Cell_size", cell_sizing);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Cell_shape", cell_shape);
|
|
xml_perf_set_technique();
|
|
|
|
Exit_code res;
|
|
for(int j=0; j<num_iteration; ++j)
|
|
{
|
|
std::cout << std::endl << "Refinement #" << j << "..." << std::endl;
|
|
|
|
if(input == "Klein_function")
|
|
{
|
|
res = make_mesh_implicit(input, Klein_function(),
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape);
|
|
}
|
|
else if(input == "Tanglecube_function")
|
|
{
|
|
res = make_mesh_implicit(input, Tanglecube_function(),
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape);
|
|
}
|
|
else if(input == "Sphere_function")
|
|
{
|
|
Sphere_function f(1.);
|
|
res = make_mesh_implicit(input, f,
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape);
|
|
}
|
|
else if(input == "Thin_cylinder_function")
|
|
{
|
|
Cylinder_function f(0.05, 3.);
|
|
res = make_mesh_implicit(input, f,
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape);
|
|
}
|
|
else if(input == "Pancake_function")
|
|
{
|
|
Cylinder_function f(3., 0.1);
|
|
res = make_mesh_implicit(input, f,
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape);
|
|
}
|
|
else // not a known implicit function
|
|
{
|
|
// Assume it's a CGAL data file...
|
|
std::string full_path = CGAL::data_file_path(input);
|
|
|
|
// ...and if it is not, then take it as it is
|
|
if(!std::ifstream(full_path).good())
|
|
full_path = input;
|
|
|
|
const std::string extension = CGAL::IO::internal::get_file_extension(input);
|
|
if(extension == "inr")
|
|
{
|
|
res = make_mesh_3D_images(full_path,
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape);
|
|
}
|
|
else // assume it's a polyhedron
|
|
{
|
|
res = make_mesh_polyhedron(full_path,
|
|
facet_sizing, facet_approx, facet_angle,
|
|
cell_sizing, cell_shape);
|
|
}
|
|
}
|
|
|
|
std::cout << "Refinement #" << j << " done." << std::endl;
|
|
std::cout << std::endl << "---------------------------------" << std::endl << std::endl;
|
|
|
|
XML_perf_data::commit();
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
// reads filename & input parameters either from argv or from a script file
|
|
int main(int argc, char** argv)
|
|
{
|
|
std::cout.precision(17);
|
|
std::cerr.precision(17);
|
|
|
|
// for the default xml filename, check XML_perf_data::build_filename()
|
|
if(argc > 1)
|
|
XML_perf_data::default_filename = argv[1];
|
|
|
|
#if defined(CHECK_MEMORY_LEAKS_ON_MSVC) && defined(_MSC_VER)
|
|
_CrtSetDbgFlag ( _CRTDtbbBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
|
#endif
|
|
|
|
#ifdef CGAL_CONCURRENT_MESH_3
|
|
Concurrent_mesher_config::load_config_file(CONCURRENT_MESHER_CONFIG_FILENAME, true);
|
|
|
|
int max_nb_threads = Concurrent_mesher_config::get().num_threads;
|
|
if(max_nb_threads == -1) // if not set in the config file, take the max available
|
|
max_nb_threads = tbb::this_task_arena::max_concurrency();
|
|
#endif
|
|
|
|
Exit_code res;
|
|
|
|
#ifdef CGAL_CONCURRENT_MESH_3
|
|
#ifdef BENCHMARK_WITH_1_TO_MAX_THREADS
|
|
for(int num_threads=1; num_threads<=max_nb_threads; ++num_threads)
|
|
#else
|
|
int num_threads = max_nb_threads;
|
|
#endif // BENCHMARK_WITH_1_TO_MAX_THREADS
|
|
#endif // CGAL_CONCURRENT_MESH_3
|
|
{
|
|
#ifdef CGAL_CONCURRENT_MESH_3
|
|
std::cout << "-- Parallel Mesh_3 --" << std::endl;
|
|
tbb::global_control control(tbb::global_control::max_allowed_parallelism, num_threads);
|
|
display_info(num_threads);
|
|
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Num_threads", num_threads);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Lockgrid_size", Concurrent_mesher_config::get().locking_grid_num_cells_per_axis);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Lock_radius", Concurrent_mesher_config::get().first_grid_lock_radius);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Statgrid_size", Concurrent_mesher_config::get().work_stats_grid_num_cells_per_axis);
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Num_work_items_per_batch", Concurrent_mesher_config::get().num_work_items_per_batch);
|
|
#else
|
|
std::cout << "-- Sequential Mesh_3 --" << std::endl;
|
|
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Num_threads", "N/A");
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Lockgrid_size", "N/A");
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Lock_radius", "N/A");
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Statgrid_size", "N/A");
|
|
CGAL_MESH_3_SET_PERFORMANCE_DATA("Num_work_items_per_batch", "N/A");
|
|
#endif
|
|
|
|
// Script file format: each line gives
|
|
// - Filename (polyhedron and image) or "XXX_function" (implicit)
|
|
// - Facet and cell criteria
|
|
// - Number of iterations with these parameters
|
|
std::ifstream script_file;
|
|
script_file.open(BENCHMARK_INPUTS_FILENAME);
|
|
if(script_file.is_open())
|
|
{
|
|
std::cout << "Found inputs file '" << BENCHMARK_INPUTS_FILENAME << "'" << std::endl;
|
|
|
|
std::string line;
|
|
while(std::getline(script_file, line))
|
|
{
|
|
if(line.empty() || line[0] == '#') // lines starting with '#' are ignored
|
|
continue;
|
|
|
|
std::cout << std::endl << std::endl;
|
|
std::cout << "*****************************************" << std::endl;
|
|
std::cout << "******* " << line << std::endl;
|
|
std::cout << "*****************************************" << std::endl;
|
|
|
|
std::stringstream sstr(line);
|
|
|
|
std::string input;
|
|
double facet_approx, facet_sizing, facet_angle;
|
|
double cell_sizing, cell_shape;
|
|
int num_iteration;
|
|
if(!(sstr >> input
|
|
>> facet_approx
|
|
>> facet_sizing
|
|
>> facet_angle
|
|
>> cell_sizing
|
|
>> cell_shape
|
|
>> num_iteration))
|
|
{
|
|
std::cerr << "Error: failed to read input" << std::endl;
|
|
return INPUT_IS_INVALID;
|
|
}
|
|
|
|
res = run(input,
|
|
facet_approx, facet_sizing, facet_angle,
|
|
cell_sizing, cell_shape,
|
|
num_iteration);
|
|
}
|
|
}
|
|
else // no script
|
|
{
|
|
std::cout << "Inputs file '" << BENCHMARK_INPUTS_FILENAME << "' NOT found." << std::endl;
|
|
|
|
// If the script is empty, use the command line arguments:
|
|
// [this_program]
|
|
// - filename
|
|
// - facet_sizing
|
|
// - facet_approx
|
|
// - facet_angle
|
|
// - cell_sizing
|
|
// - cell_shape
|
|
// - num_iteration
|
|
|
|
std::string input = (argc > 2) ? argv[2] : "Sphere_function"; // @fixme klein assertion?
|
|
double facet_sizing = (argc > 3) ? std::stod(argv[3]) : DEFAULT_FACE_SIZE;
|
|
double facet_approx = (argc > 4) ? std::stod(argv[4]) : DEFAULT_FACE_APPROX;
|
|
double facet_angle = (argc > 5) ? std::stod(argv[5]) : DEFAULT_FACE_ANGLE; // 25°
|
|
double cell_sizing = (argc > 6) ? std::stod(argv[6]) : DEFAULT_CELL_SIZE;
|
|
double cell_shape = (argc > 7) ? std::stod(argv[7]) : DEFAULT_CELL_RADIUS_RATIO; // 3
|
|
|
|
if(facet_sizing <= 0)
|
|
facet_sizing = DEFAULT_FACE_SIZE;
|
|
if(facet_approx <= 0)
|
|
facet_approx = DEFAULT_FACE_APPROX;
|
|
if(facet_angle <= 0)
|
|
facet_angle = DEFAULT_FACE_ANGLE;
|
|
if(cell_sizing <= 0)
|
|
cell_sizing = DEFAULT_CELL_SIZE;
|
|
if(cell_shape <= 0)
|
|
cell_shape = DEFAULT_CELL_RADIUS_RATIO;
|
|
|
|
res = run(input,
|
|
facet_approx, facet_sizing, facet_angle,
|
|
cell_sizing, cell_shape,
|
|
1 /*num_iteration*/);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|