54 std::cout<<
"Usage: "<<cmd<<
" [options] infile\n"
56 <<
" -h, --help\n\tHelp! Prints this message.\n"
57 <<
" -v, --verbose\n\tVerbose output.\n"
58 <<
" -c factor, --compression factor\n\tCurrently an art...\n";
62 int parse_arguments(
int argc,
char **argv, std::string &infilename,
bool &verbose,
double &factor){
73 struct option longOptions[] = {
75 {
"verbose", 0, 0,
'v'},
76 {
"compression", optional_argument, 0,
'c'},
82 const char *shortopts =
"hvc:";
87 c = getopt_long(argc, argv, shortopts, longOptions, &optionIndex);
99 factor = atof(optarg);
104 std::cerr<<
"ERROR: unknown option or missing argument\n";
108 std::cerr<<
"ERROR: missing argument\n";
113 std::cerr<<
"ERROR: getopt returned unrecognized character code\n";
118 infilename = std::string(argv[argc-1]);
128 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
131 std::cout<<operation<<
": step in quality (mean, min): ("<<qmean<<
", "<<qmin<<
")"<<std::endl;
134 int main(
int argc,
char **argv){
135 int required_thread_support=MPI_THREAD_SINGLE;
136 int provided_thread_support;
137 MPI_Init_thread(&argc, &argv, required_thread_support, &provided_thread_support);
138 assert(required_thread_support==provided_thread_support);
141 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
148 std::string infilename, outfilename;
155 vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
156 reader->SetFileName(infilename.c_str());
157 vtkSmartPointer<vtkImageGaussianSmooth> gsmooth = vtkSmartPointer<vtkImageGaussianSmooth>::New();
158 gsmooth->SetStandardDeviation(9);
159 gsmooth->SetDimensionality(2);
160 #if VTK_MAJOR_VERSION < 6
161 gsmooth->SetInput(reader->GetOutput());
163 gsmooth->SetInputConnection(reader->GetOutputPort());
168 vtkSmartPointer<vtkDataSetTriangleFilter> image2ug = vtkSmartPointer<vtkDataSetTriangleFilter>::New();
169 #if VTK_MAJOR_VERSION < 6
170 image2ug->SetInput(gsmooth->GetOutput());
172 image2ug->SetInputConnection(gsmooth->GetOutputPort());
175 vtkUnstructuredGrid *ug = image2ug->GetOutput();
176 #if VTK_MAJOR_VERSION < 6
180 size_t NNodes = ug->GetNumberOfPoints();
181 std::vector<double> x(NNodes),y(NNodes), imageR(NNodes), imageG(NNodes), imageB(NNodes);
182 for(
size_t i=0;i<NNodes;i++){
184 ug->GetPoints()->GetPoint(i, r);
188 const double *tuple = ug->GetPointData()->GetArray(0)->GetTuple(i);
190 imageR[i] = tuple[0];
191 imageG[i] = tuple[1];
192 imageB[i] = tuple[2];
195 int cell_type = ug->GetCell(0)->GetCellType();
196 assert(cell_type==VTK_TRIANGLE);
201 size_t NElements = ug->GetNumberOfCells();
203 std::vector<int> ENList(NElements*nloc);
204 for(
size_t i=0;i<NElements;i++){
205 vtkCell *cell = ug->GetCell(i);
206 assert(cell->GetCellType()==cell_type);
208 for(
int j=0;j<nloc;j++){
209 ENList[i*nloc+j] = cell->GetPointId(j);
217 MPI_Comm_size(MPI_COMM_WORLD, &nparts);
220 std::vector<index_t> owner_range;
221 std::vector<index_t> lnn2gnn;
222 std::vector<int> node_owner;
224 std::vector<int> epart(NElements, 0), npart(NNodes, 0);
226 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
231 std::vector<int> eind(NElements*nloc);
233 for(
size_t i=0;i<NElements*nloc;i++)
236 int intNElements = NElements;
237 int intNNodes = NNodes;
239 #ifdef METIS_VER_MAJOR
240 int vsize = nloc - 1;
241 std::vector<int> eptr(NElements+1);
242 for(
size_t i=0;i<NElements;i++)
243 eptr[i+1] = eptr[i]+nloc;
244 METIS_PartMeshNodal(&intNElements,
257 std::vector<int> etype(NElements);
258 for(
size_t i=0;i<NElements;i++)
261 METIS_PartMeshNodal(&intNElements,
274 MPI_Datatype MPI_INDEX_T = mpi_index_t_wrapper.
mpi_type;
276 MPI_Bcast(&(epart[0]), NElements, MPI_INDEX_T, 0, MPI_COMM_WORLD);
277 MPI_Bcast(&(npart[0]), NNodes, MPI_INDEX_T, 0, MPI_COMM_WORLD);
280 std::vector< std::vector<index_t> > node_partition(nparts);
281 for(
size_t i=0;i<NNodes;i++)
282 node_partition[npart[i]].push_back(i);
284 #ifdef HAVE_BOOST_UNORDERED_MAP_HPP
285 boost::unordered_map<index_t, index_t> renumber;
287 std::map<index_t, index_t> renumber;
291 owner_range.push_back(0);
292 for(
int i=0;i<nparts;i++){
293 int pNNodes = node_partition[i].size();
294 owner_range.push_back(owner_range[i]+pNNodes);
295 for(
int j=0;j<pNNodes;j++)
296 renumber[node_partition[i][j]] = pos++;
299 std::vector<index_t> element_partition;
300 std::set<index_t> halo_nodes;
301 for(
size_t i=0;i<NElements;i++){
302 std::set<index_t> residency;
303 for(
int j=0;j<nloc;j++)
304 residency.insert(npart[ENList[i*nloc+j]]);
306 if(residency.count(rank)){
307 element_partition.push_back(i);
309 for(
int j=0;j<nloc;j++){
310 index_t nid = ENList[i*nloc+j];
312 halo_nodes.insert(nid);
318 for(
typename std::set<index_t>::const_iterator it=halo_nodes.begin();it!=halo_nodes.end();++it){
319 node_partition[rank].push_back(*it);
323 NNodes = node_partition[rank].size();
324 lnn2gnn.resize(NNodes);
325 node_owner.resize(NNodes);
326 for(
size_t i=0;i<NNodes;i++){
327 index_t nid = node_partition[rank][i];
330 node_owner[i] = npart[nid];
334 std::vector<double> lx(NNodes), ly(NNodes), lz(NNodes), limageR(NNodes), limageG(NNodes), limageB(NNodes);
335 for(
size_t i=0;i<NNodes;i++){
336 lx[i] = x[node_partition[rank][i]];
337 ly[i] = y[node_partition[rank][i]];
339 limageR[i] = imageR[node_partition[rank][i]];
340 limageG[i] = imageG[node_partition[rank][i]];
341 limageB[i] = imageB[node_partition[rank][i]];
344 NElements = element_partition.size();
345 std::vector<index_t> lENList(NElements*nloc);
346 for(
size_t i=0;i<NElements;i++){
347 for(
int j=0;j<nloc;j++){
348 index_t nid = renumber[ENList[element_partition[i]*nloc+j]];
349 lENList[i*nloc+j] = nid;
356 imageR.swap(limageR);
357 imageG.swap(limageG);
358 imageB.swap(limageB);
359 ENList.swap(lENList);
361 MPI_Comm comm = MPI_COMM_WORLD;
363 mesh =
new Mesh<double>(NNodes, NElements, &(ENList[0]), &(x[0]), &(y[0]), &(lnn2gnn[0]), &(owner_range[0]), comm);
365 mesh =
new Mesh<double>(NNodes, NElements, &(ENList[0]), &(x[0]), &(y[0]));
373 metric_field.
add_field(imageR.data(), 5.0, 1);
374 std::cout<<
"Predicted number of elementsR: "<<metric_field.
predict_nelements()<<std::endl;
381 std::cout<<
"Predicted number of elements1: "<<metric_field.
predict_nelements()<<std::endl;
391 time_metric = (
get_wtime() - time_metric);
400 double L_up = sqrt(2.0);
406 double time_coarsen=0, time_swapping=0;
407 for(
size_t i=0;i<5;i++){
409 std::cout<<
"INFO: Sweep "<<i<<std::endl;
412 coarsen.
coarsen(L_up, L_up,
true);
429 time_smooth = (
get_wtime() - time_smooth);
434 std::cout<<
"Times for metric, coarsen, swapping, smoothing = "<<time_metric<<
", "<<time_coarsen<<
", "<<time_swapping<<
", "<<time_smooth<<std::endl;
436 if(outfilename.size()==0)
void smart_laplacian(int max_iterations=10, double quality_tol=-1.0)
void update_mesh()
Update the metric field on the mesh.
void cout_quality(const Mesh< double > *mesh, std::string operation)
Performs 2D mesh coarsening.
double get_qmean() const
Get the element mean quality in metric space.
Performs edge/face swapping.
double get_qmin() const
Get the element minimum quality in metric space.
void coarsen(real_t L_low, real_t L_max, bool enable_sliver_deletion=false)
Constructs metric tensor field which encodes anisotropic edge size information.
void add_field(const real_t *psi, const real_t target_error, int p_norm=-1)
int parse_arguments(int argc, char **argv, std::string &infilename, bool &verbose, double &factor)
real_t predict_nelements()
void apply_min_edge_length(real_t min_len)
void swap(real_t quality_tolerance)
const MPI_Datatype mpi_type
int main(int argc, char **argv)
Applies Laplacian smoothen in metric space.
void optimisation_linf(int max_iterations=10, double quality_tol=-1.0)