MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
mesh-explorer.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11//
12// -----------------------------------------------------
13// Mesh Explorer Miniapp: Explore and manipulate meshes
14// -----------------------------------------------------
15//
16// This miniapp is a handy tool to examine, visualize and manipulate a given
17// mesh. Some of its features are:
18//
19// - visualizing of mesh materials and individual mesh elements
20// - mesh scaling, randomization, and general transformation
21// - manipulation of the mesh curvature
22// - the ability to simulate parallel partitioning
23// - quantitative and visual reports of mesh quality
24//
25// Compile with: make mesh-explorer
26//
27// Sample runs: mesh-explorer
28// mesh-explorer -m ../../data/beam-tri.mesh
29// mesh-explorer -m ../../data/star-q2.mesh
30// mesh-explorer -m ../../data/disc-nurbs.mesh
31// mesh-explorer -m ../../data/escher-p3.mesh
32// mesh-explorer -m ../../data/mobius-strip.mesh
33
34#include "mfem.hpp"
36#include <fstream>
37#include <limits>
38#include <cstdlib>
39
40using namespace mfem;
41using namespace std;
42
43// This transformation can be applied to a mesh with the 't' menu option.
44void transformation(const Vector &p, Vector &v)
45{
46 // simple shear transformation
47 real_t s = 0.1;
48
49 if (p.Size() == 3)
50 {
51 v(0) = p(0) + s*p(1) + s*p(2);
52 v(1) = p(1) + s*p(2) + s*p(0);
53 v(2) = p(2);
54 }
55 else if (p.Size() == 2)
56 {
57 v(0) = p(0) + s*p(1);
58 v(1) = p(1) + s*p(0);
59 }
60 else
61 {
62 v = p;
63 }
64}
65
66// This function is used with the 'r' menu option, sub-option 'l' to refine a
67// mesh locally in a region, defined by return values <= region_eps.
70{
71 const real_t x = p(0), y = p(1);
72 // here we describe the region: (x <= 1/4) && (y >= 0) && (y <= 1)
73 return std::max(std::max(x - (real_t) 0.25, -y), y - (real_t) 1.0);
74}
75
76// The projection of this function can be plotted with the 'l' menu option
78{
79 real_t x = p(0);
80 real_t y = p.Size() > 1 ? p(1) : 0.0;
81 real_t z = p.Size() > 2 ? p(2) : 0.0;
82
83 if (1)
84 {
85 // torus in the xy-plane
86 const real_t r_big = 2.0;
87 const real_t r_small = 1.0;
88 return hypot(r_big - hypot(x, y), z) - r_small;
89 }
90 if (0)
91 {
92 // sphere at the origin:
93 const real_t r = 1.0;
94 return hypot(hypot(x, y), z) - r;
95 }
96}
97
98Mesh *read_par_mesh(int np, const char *mesh_prefix, Array<int>& partitioning,
99 Array<int>& bdr_partitioning)
100{
101 Mesh *mesh;
102 Array<Mesh *> mesh_array;
103
104 mesh_array.SetSize(np);
105 for (int p = 0; p < np; p++)
106 {
107 ostringstream fname;
108 fname << mesh_prefix << '.' << setfill('0') << setw(6) << p;
109 ifgzstream meshin(fname.str().c_str());
110 if (!meshin)
111 {
112 cerr << "Can not open mesh file: " << fname.str().c_str()
113 << '!' << endl;
114 for (p--; p >= 0; p--)
115 {
116 delete mesh_array[p];
117 }
118 return NULL;
119 }
120 mesh_array[p] = new Mesh(meshin, 1, 0);
121 // Assign corresponding processor number to element + boundary partitions
122 for (int i = 0; i < mesh_array[p]->GetNE(); i++)
123 {
124 partitioning.Append(p);
125 }
126 for (int i = 0; i < mesh_array[p]->GetNBE(); i++)
127 {
128 bdr_partitioning.Append(p);
129 }
130 }
131 mesh = new Mesh(mesh_array, np);
132
133 for (int p = 0; p < np; p++)
134 {
135 delete mesh_array[np-1-p];
136 }
137 mesh_array.DeleteAll();
138
139 return mesh;
140}
141
142// Given a 3D mesh, produce a 2D mesh consisting of its boundary elements.
143// We guarantee that the skin preserves the boundary index order.
145{
146 // Determine mapping from vertex to boundary vertex
147 Array<int> v2v(mesh->GetNV());
148 v2v = -1;
149 for (int i = 0; i < mesh->GetNBE(); i++)
150 {
151 Element *el = mesh->GetBdrElement(i);
152 int *v = el->GetVertices();
153 int nv = el->GetNVertices();
154 for (int j = 0; j < nv; j++)
155 {
156 v2v[v[j]] = 0;
157 }
158 }
159 int nbvt = 0;
160 for (int i = 0; i < v2v.Size(); i++)
161 {
162 if (v2v[i] == 0)
163 {
164 v2v[i] = nbvt++;
165 }
166 }
167
168 // Create a new mesh for the boundary
169 Mesh * bmesh = new Mesh(mesh->Dimension() - 1, nbvt, mesh->GetNBE(),
170 0, mesh->SpaceDimension());
171
172 // Copy vertices to the boundary mesh
173 nbvt = 0;
174 for (int i = 0; i < v2v.Size(); i++)
175 {
176 if (v2v[i] >= 0)
177 {
178 real_t *c = mesh->GetVertex(i);
179 bmesh->AddVertex(c);
180 nbvt++;
181 }
182 }
183
184 // Copy elements to the boundary mesh
185 int bv[4];
186 for (int i = 0; i < mesh->GetNBE(); i++)
187 {
188 Element *el = mesh->GetBdrElement(i);
189 int *v = el->GetVertices();
190 int nv = el->GetNVertices();
191
192 for (int j = 0; j < nv; j++)
193 {
194 bv[j] = v2v[v[j]];
195 }
196
197 switch (el->GetGeometryType())
198 {
200 bmesh->AddSegment(bv, el->GetAttribute());
201 break;
203 bmesh->AddTriangle(bv, el->GetAttribute());
204 break;
205 case Geometry::SQUARE:
206 bmesh->AddQuad(bv, el->GetAttribute());
207 break;
208 default:
209 break; // This should not happen
210 }
211
212 }
213 bmesh->FinalizeTopology();
214
215 // Copy GridFunction describing nodes if present
216 if (mesh->GetNodes())
217 {
218 FiniteElementSpace *fes = mesh->GetNodes()->FESpace();
219 const FiniteElementCollection *fec = fes->FEColl();
220 if (dynamic_cast<const H1_FECollection*>(fec))
221 {
222 FiniteElementCollection *fec_copy =
224 FiniteElementSpace *fes_copy =
225 new FiniteElementSpace(*fes, bmesh, fec_copy);
226 GridFunction *bdr_nodes = new GridFunction(fes_copy);
227 bdr_nodes->MakeOwner(fec_copy);
228
229 bmesh->NewNodes(*bdr_nodes, true);
230
231 Array<int> vdofs;
232 Array<int> bvdofs;
233 Vector v;
234 for (int i=0; i<mesh->GetNBE(); i++)
235 {
236 fes->GetBdrElementVDofs(i, vdofs);
237 mesh->GetNodes()->GetSubVector(vdofs, v);
238
239 fes_copy->GetElementVDofs(i, bvdofs);
240 bdr_nodes->SetSubVector(bvdofs, v);
241 }
242 }
243 else
244 {
245 cout << "\nDiscontinuous nodes not yet supported" << endl;
246 }
247 }
248
249 return bmesh;
250}
251
252void recover_bdr_partitioning(const Mesh* mesh, const Array<int>& partitioning,
253 Array<int>& bdr_partitioning)
254{
255 bdr_partitioning.SetSize(mesh->GetNBE());
256 int info, e;
257 for (int be = 0; be < mesh->GetNBE(); be++)
258 {
259 mesh->GetBdrElementAdjacentElement(be, e, info);
260 bdr_partitioning[be] = partitioning[e];
261 }
262}
263
264int main (int argc, char *argv[])
265{
266 int np = 0;
267 const char *mesh_file = "../../data/beam-hex.mesh";
268 int visport = 19916;
269 bool refine = true;
270
271 OptionsParser args(argc, argv);
272 args.AddOption(&mesh_file, "-m", "--mesh",
273 "Mesh file to visualize.");
274 args.AddOption(&np, "-np", "--num-proc",
275 "Load mesh from multiple processors.");
276 args.AddOption(&refine, "-ref", "--refinement", "-no-ref", "--no-refinement",
277 "Prepare the mesh for refinement or not.");
278 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
279 args.Parse();
280 if (!args.Good())
281 {
282 if (!args.Help())
283 {
284 args.PrintError(cout);
285 cout << endl;
286 }
287 cout << "Visualize and manipulate a serial mesh:\n"
288 << " mesh-explorer -m <mesh_file>\n"
289 << "Visualize and manipulate a parallel mesh:\n"
290 << " mesh-explorer -np <#proc> -m <mesh_prefix>\n" << endl
291 << "All Options:\n";
292 args.PrintHelp(cout);
293 return 1;
294 }
295 args.PrintOptions(cout);
296
297 Mesh *mesh;
298 Mesh *bdr_mesh = NULL;
299
300 // Helper to distinguish whether we use a parallel or serial mesh.
301 const bool use_par_mesh = np > 0;
302
303 // Helper for visualizing the partitioning.
304 Array<int> partitioning;
305 Array<int> bdr_partitioning;
306 Array<int> elem_partitioning;
307 if (!use_par_mesh)
308 {
309 mesh = new Mesh(mesh_file, 1, refine);
310 partitioning.SetSize(mesh->GetNE());
311 partitioning = 0;
312 bdr_partitioning.SetSize(mesh->GetNBE());
313 bdr_partitioning = 0;
314 elem_partitioning.SetSize(mesh->GetNE());
315 elem_partitioning = 0;
316 np = 1;
317 }
318 else
319 {
320 mesh = read_par_mesh(np, mesh_file, partitioning, bdr_partitioning);
321 if (mesh == NULL)
322 {
323 return 3;
324 }
325 }
326 int dim = mesh->Dimension();
327 int sdim = mesh->SpaceDimension();
328
329 FiniteElementCollection *bdr_attr_fec = NULL;
330 FiniteElementCollection *attr_fec;
331 if (dim == 2)
332 {
333 attr_fec = new Const2DFECollection;
334 }
335 else
336 {
337 bdr_attr_fec = new Const2DFECollection;
338 attr_fec = new Const3DFECollection;
339 }
340
341 int print_char = 1;
342 while (1)
343 {
344 if (print_char)
345 {
346 cout << endl;
347 mesh->PrintCharacteristics();
348 cout << "boundary attribs :";
349 for (int i = 0; i < mesh->bdr_attributes.Size(); i++)
350 {
351 cout << ' ' << mesh->bdr_attributes[i];
352 }
353 cout << '\n' << "material attribs :";
354 for (int i = 0; i < mesh->attributes.Size(); i++)
355 {
356 cout << ' ' << mesh->attributes[i];
357 }
358 cout << endl;
359 cout << "mesh curvature : ";
360 if (mesh->GetNodalFESpace() != NULL)
361 {
362 cout << mesh->GetNodalFESpace()->FEColl()->Name() << endl;
363 }
364 else
365 {
366 cout << "NONE" << endl;
367 }
368 }
369 print_char = 0;
370 cout << endl;
371 cout << "What would you like to do?\n"
372 "r) Refine\n"
373 "c) Change curvature\n"
374 "i) Increase space dimension\n"
375 "s) Scale\n"
376 "t) Transform\n"
377 "j) Jitter\n"
378 "v) View mesh\n"
379 "P) View partitioning\n"
380 "m) View materials\n"
381 "b) View boundary\n"
382 "B) View boundary partitioning\n"
383 "e) View elements\n"
384 "h) View element sizes, h\n"
385 "k) View element ratios, kappa\n"
386 "J) View scaled Jacobian\n"
387 "l) Plot a function\n"
388 "x) Print sub-element stats\n"
389 "f) Find physical point in reference space\n"
390 "p) Generate a partitioning\n"
391 "o) Reorder elements\n"
392 "S) Save in MFEM serial format\n"
393 "T) Save in MFEM parallel format using the current partitioning\n"
394 "V) Save in VTK format (only linear and quadratic meshes)\n"
395#ifdef MFEM_USE_NETCDF
396 "X) Save in Exodus II format (only linear and quadratic meshes)\n"
397#endif
398 "D) Save as a DataCollection\n"
399 "q) Quit\n"
400#ifdef MFEM_USE_ZLIB
401 "Z) Save in MFEM format with compression\n"
402#endif
403 "--> " << flush;
404 char mk;
405 cin >> mk;
406 if (!cin) { break; }
407
408 if (mk == 'q')
409 {
410 break;
411 }
412
413 if (mk == 'r')
414 {
415 cout <<
416 "Choose type of refinement:\n"
417 "s) standard refinement with Mesh::UniformRefinement()\n"
418 "b) Mesh::UniformRefinement() (bisection for tet meshes)\n"
419 "u) uniform refinement with a factor\n"
420 "g) non-uniform refinement (Gauss-Lobatto) with a factor\n"
421 "n) NURBS refinement with factors\n"
422 "p) NURBS NC-patch refinement with factors\n"
423 "c) NURBS coarsening with a factor\n"
424 "l) refine locally using the region() function\n"
425 "r) random refinement with a probability\n"
426 "--> " << flush;
427 char sk;
428 cin >> sk;
429 switch (sk)
430 {
431 case 's':
432 mesh->UniformRefinement();
433 // Make sure tet-only meshes are marked for local refinement.
434 mesh->Finalize(true);
435 break;
436 case 'b':
437 mesh->UniformRefinement(1); // ref_algo = 1
438 break;
439 case 'u':
440 case 'g':
441 {
442 cout << "enter refinement factor --> " << flush;
443 int ref_factor;
444 cin >> ref_factor;
445 if (ref_factor <= 1 || ref_factor > 32) { break; }
446 int ref_type = (sk == 'u') ? BasisType::ClosedUniform :
448 *mesh = Mesh::MakeRefined(*mesh, ref_factor, ref_type);
449 break;
450 }
451 case 'n':
452 {
453 Array<int> ref_factors(dim);
454 cout << "enter refinement factor, 1st dimension --> " << flush;
455 cin >> ref_factors[0];
456 cout << "enter refinement factor, 2nd dimension --> " << flush;
457 cin >> ref_factors[1];
458 if (dim == 3)
459 {
460 cout << "enter refinement factor, 3rd dimension --> "
461 << flush;
462 cin >> ref_factors[2];
463 }
464 for (auto ref_factor : ref_factors)
465 if (ref_factor <= 1 || ref_factor > 32) { break; }
466
467 char input_tol = 'n';
468 cout << "enter NURBS tolerance? [y/n] --> " << flush;
469 cin >> input_tol;
470
471 real_t tol = 1.0e-12; // Default value
472 if (input_tol == 'y')
473 {
474 cout << "enter NURBS tolerance --> " << flush;
475 cin >> tol;
476 }
477
478 mesh->NURBSUniformRefinement(ref_factors, tol);
479 break;
480 }
481 case 'p':
482 {
483 int ref_factor;
484 cout << "enter default refinement factor --> " << flush;
485 cin >> ref_factor;
486 if (ref_factor <= 1 || ref_factor > 32) { break; }
487
488 cout << "enter knot vector refinement factor filename? [y/n] ---> " << flush;
489 char input_kvf = 'n';
490 cin >> input_kvf;
491 std::string kvf;
492 if (input_kvf == 'y')
493 {
494 cout << "enter filename ---> " << flush;
495 cin >> kvf;
496 }
497 mesh->RefineNURBSWithKVFactors(ref_factor, kvf);
498 break;
499 }
500 case 'c':
501 {
502 cout << "enter coarsening factor --> " << flush;
503 int coarsen_factor;
504 cin >> coarsen_factor;
505 if (coarsen_factor <= 1 || coarsen_factor > 32) { break; }
506
507 char input_tol = 'n';
508 cout << "enter NURBS tolerance? [y/n] --> " << flush;
509 cin >> input_tol;
510
511 real_t tol = 1.0e-12; // Default value
512 if (input_tol == 'y')
513 {
514 cout << "enter NURBS tolerance --> " << flush;
515 cin >> tol;
516 }
517
518 mesh->NURBSCoarsening(coarsen_factor, tol);
519 break;
520 }
521 case 'l':
522 {
523 Vector pt;
524 Array<int> marked_elements;
525 for (int i = 0; i < mesh->GetNE(); i++)
526 {
527 // check all nodes of the element
529 mesh->GetElementTransformation(i, &T);
530 for (int j = 0; j < T.GetPointMat().Width(); j++)
531 {
533 if (region(pt) <= region_eps)
534 {
535 marked_elements.Append(i);
536 break;
537 }
538 }
539 }
540 mesh->GeneralRefinement(marked_elements);
541 break;
542 }
543 case 'r':
544 {
545 bool nc_simplices = true;
546 mesh->EnsureNCMesh(nc_simplices);
547 cout << "enter probability --> " << flush;
548 real_t probability;
549 cin >> probability;
550 if (probability < 0.0 || probability > 1.0) { break; }
551 mesh->RandomRefinement(probability);
552 break;
553 }
554 }
555 print_char = 1;
556 }
557
558 if (mk == 'i')
559 {
560 int curr_sdim = mesh->SpaceDimension();
561 cout << "Current space dimension is " << curr_sdim << "\n";
562 cout << "Enter new space dimension --> " << flush;
563 int new_sdim;
564 cin >> new_sdim;
565 if (new_sdim > curr_sdim && new_sdim <= 3)
566 {
567 if (mesh->GetNodes() == NULL)
568 {
569 mesh->SetCurvature(1, false, new_sdim); // Set Space Dimension
570 mesh->SetCurvature(-1); // Remove Nodes GridFunction created
571 // // by the previous line
572 }
573 else
574 {
575 const FiniteElementSpace *fes = mesh->GetNodalFESpace();
576 const int order = fes->GetMaxElementOrder();
577 const FiniteElementCollection *fec = fes->FEColl();
578 const bool discont = dynamic_cast<const L2_FECollection*>(fec);
579 mesh->SetCurvature(order, discont, new_sdim);
580 }
581 }
582 else
583 {
584 cout << "New space dimension must be greater than current space "
585 << "dimension and less than 4." << endl;
586 }
587 }
588
589 if (mk == 'c')
590 {
591 int p;
592 cout << "enter new order for mesh curvature --> " << flush;
593 cin >> p;
594 mesh->SetCurvature(p > 0 ? p : -p, p <= 0);
595 print_char = 1;
596 }
597
598 if (mk == 's')
599 {
600 real_t factor;
601 cout << "scaling factor ---> " << flush;
602 cin >> factor;
603
604 GridFunction *nodes = mesh->GetNodes();
605 if (nodes == NULL)
606 {
607 for (int i = 0; i < mesh->GetNV(); i++)
608 {
609 real_t *v = mesh->GetVertex(i);
610 v[0] *= factor;
611 v[1] *= factor;
612 if (dim == 3)
613 {
614 v[2] *= factor;
615 }
616 }
617 }
618 else
619 {
620 *nodes *= factor;
621 }
622
623 print_char = 1;
624 }
625
626 if (mk == 't')
627 {
628 char type;
629 cout << "Choose a transformation:\n"
630 "u) User-defined transform through mesh-explorer::transformation()\n"
631 "a) Affine transform\n"
632 "k) Kershaw transform\n"
633 "s) Spiral transform\n"<< "---> " << flush;
634 cin >> type;
635 if (type == 'u')
636 {
638 }
639 else if (type == 'a')
640 {
641 DenseMatrix A(sdim);
642 Vector b(sdim);
643
644 char tmtype;
645 cout << "Type of transformation matrix:\n"
646 "i) Identity\n"
647 "r) Rotation\n"
648 "s) Scale\n"
649 "g) General\n" << " ---> " << flush;
650 cin >> tmtype;
651
652 if (tmtype == 'i')
653 {
654 A = 0.0;
655 A(0,0) = 1.0;
656 if (sdim > 1) { A(1,1) = 1.0; }
657 if (sdim > 2) { A(2,2) = 1.0; }
658 }
659 if (tmtype == 'r')
660 {
661 if (sdim == 2)
662 {
663 real_t angle_deg;
664 cout << "Rotation angle (degrees) --> " << flush;
665 cin >> angle_deg;
666 const real_t angle = angle_deg * M_PI / 180.0;
667 A(0,0) = cos(angle);
668 A(1,0) = sin(angle);
669 A(0,1) = -A(1,0);
670 A(1,1) = A(0,0);
671 }
672 else
673 {
674 real_t a_deg, b_deg, c_deg;
675 cout << "Euler angles z-x-z (degrees) --> " << flush;
676 cin >> a_deg >> b_deg >> c_deg;
677
678 const real_t alpha = a_deg * M_PI / 180.0;
679 const real_t beta = b_deg * M_PI / 180.0;
680 const real_t gamma = c_deg * M_PI / 180.0;
681
682 const real_t ca = cos(alpha), sa = sin(alpha);
683 const real_t cb = cos(beta ), sb = sin(beta );
684 const real_t cc = cos(gamma), sc = sin(gamma);
685
686 A(0,0) = ca * cc - cb * sa * sc;
687 A(0,1) = -ca * sc - cb * cc * sa;
688 A(0,2) = sa * sb;
689
690 A(1,0) = cc * sa + ca * cb * sc;
691 A(1,1) = ca * cb * cc - sa * sc;
692 A(1,2) = -ca * sb;
693
694 A(2,0) = sb * sc;
695 A(2,1) = cc * sb;
696 A(2,2) = cb;
697 }
698 }
699 if (tmtype == 's')
700 {
701 A = 0.0;
702 cout << "Scale factors for each cartesian direction --> "
703 << flush;
704 cin >> A(0,0);
705 if (sdim > 1) { cin >> A(1,1); }
706 if (sdim > 2) { cin >> A(2,2); }
707 }
708 if (tmtype == 'g')
709 {
710 cout << "General matrix entries in column major order --> "
711 << flush;
712 for (int j=0; j<sdim; j++)
713 for (int i=0; i<sdim; i++)
714 {
715 cin >> A(i,j);
716 }
717
718 const real_t detA = A.Det();
719 if (detA <= 0.0)
720 {
721 cout << "Warning - transformation matrix has non-positive "
722 << "determinant. Elements may be flattened or "
723 << "inverted.\n";
724 }
725 }
726
727 cout << "Translation vector components --> " << flush;
728 cin >> b(0);
729 if (sdim > 1) { cin >> b(1); }
730 if (sdim > 2) { cin >> b(2); }
731
732 common::AffineTransformation affineT(sdim, A, b);
733 mesh->Transform(affineT);
734 }
735 else if (type == 'k')
736 {
737 cout << "Note: For Kershaw transformation, the input must be "
738 "Cartesian aligned with nx multiple of 6 and "
739 "both ny and nz multiples of 2."
740 "Kershaw transform works for 2D meshes also.\n" << flush;
741
742 real_t epsy, epsz = 0.0;
743 cout << "Kershaw transform factor, epsy in (0, 1]) ---> " << flush;
744 cin >> epsy;
745 if (mesh->Dimension() == 3)
746 {
747 cout << "Kershaw transform factor, epsz in (0, 1]) ---> " << flush;
748 cin >> epsz;
749 }
750 common::KershawTransformation kershawT(mesh->Dimension(), epsy, epsz);
751 mesh->Transform(kershawT);
752 }
753 else if (type == 's')
754 {
755 MFEM_VERIFY(mesh->SpaceDimension() >= 2,
756 "Mesh space dimension must be at least 2 "
757 "for spiral transformation.\n");
758 cout << "Note: For Spiral transformation, the input mesh is "
759 "assumed to be in [0,1]^D.\n" << flush;
760 real_t turns, width, gap, height = 1.0;
761 cout << "Number of turns: ---> " << flush;
762 cin >> turns;
763 cout << "Width of spiral arm (e.g. 0.1) ---> " << flush;
764 cin >> width;
765 cout << "Gap between adjacent spiral arms at the end of each turn (e.g. 0.05) ---> "
766 << flush;
767 cin >> gap;
768 if (mesh->SpaceDimension() == 3)
769 {
770 cout << "Maximum spiral height ---> " << flush;
771 cin >> height;
772 }
773 common::SpiralTransformation spiralT(mesh->SpaceDimension(), turns,
774 width, gap, height);
775 mesh->Transform(spiralT);
776 }
777 else
778 {
779 MFEM_ABORT("Transformation type not supported.");
780 }
781 print_char = 1;
782 }
783
784 if (mk == 'j')
785 {
786 real_t jitter;
787 cout << "jitter factor ---> " << flush;
788 cin >> jitter;
789
790 GridFunction *nodes = mesh->GetNodes();
791
792 if (nodes == NULL)
793 {
794 cerr << "The mesh should have nodes, introduce curvature first!\n";
795 }
796 else
797 {
798 FiniteElementSpace *fespace = nodes->FESpace();
799
800 GridFunction rdm(fespace);
801 rdm.Randomize();
802 rdm -= 0.5; // shift to random values in [-0.5,0.5]
803 rdm *= jitter;
804
805 // compute minimal local mesh size
806 Vector h0(fespace->GetNDofs());
807 h0 = infinity();
808 {
809 Array<int> dofs;
810 for (int i = 0; i < fespace->GetNE(); i++)
811 {
812 fespace->GetElementDofs(i, dofs);
813 for (int j = 0; j < dofs.Size(); j++)
814 {
815 h0(dofs[j]) = std::min(h0(dofs[j]), mesh->GetElementSize(i));
816 }
817 }
818 }
819
820 // scale the random values to be of order of the local mesh size
821 for (int i = 0; i < fespace->GetNDofs(); i++)
822 {
823 for (int d = 0; d < dim; d++)
824 {
825 rdm(fespace->DofToVDof(i,d)) *= h0(i);
826 }
827 }
828
829 char move_bdr = 'n';
830 cout << "move boundary nodes? [y/n] ---> " << flush;
831 cin >> move_bdr;
832
833 // don't perturb the boundary
834 if (move_bdr == 'n')
835 {
836 Array<int> vdofs;
837 for (int i = 0; i < fespace->GetNBE(); i++)
838 {
839 fespace->GetBdrElementVDofs(i, vdofs);
840 for (int j = 0; j < vdofs.Size(); j++)
841 {
842 rdm(vdofs[j]) = 0.0;
843 }
844 }
845 }
846
847 *nodes += rdm;
848 }
849
850 print_char = 1;
851 }
852
853 if (mk == 'x')
854 {
855 int sd, nz = 0;
856 DenseMatrix J(dim);
857 real_t min_det_J, max_det_J, min_det_J_z, max_det_J_z;
858 real_t min_kappa, max_kappa, max_ratio_det_J_z;
859 min_det_J = min_kappa = infinity();
860 max_det_J = max_kappa = max_ratio_det_J_z = -infinity();
861 cout << "subdivision factor ---> " << flush;
862 cin >> sd;
863 Array<int> bad_elems_by_geom(Geometry::NumGeom);
864 bad_elems_by_geom = 0;
865 // Only print so many to keep output compact
866 const int max_to_print = 10;
867 for (int i = 0; i < mesh->GetNE(); i++)
868 {
871
872 RefinedGeometry *RefG = GlobGeometryRefiner.Refine(geom, sd, 1);
873 IntegrationRule &ir = RefG->RefPts;
874
875 min_det_J_z = infinity();
876 max_det_J_z = -infinity();
877 for (int j = 0; j < ir.GetNPoints(); j++)
878 {
879 T->SetIntPoint(&ir.IntPoint(j));
880 Geometries.JacToPerfJac(geom, T->Jacobian(), J);
881
882 real_t det_J = J.Det();
883 real_t kappa =
885
886 min_det_J_z = std::min(min_det_J_z, det_J);
887 max_det_J_z = std::max(max_det_J_z, det_J);
888
889 min_kappa = std::min(min_kappa, kappa);
890 max_kappa = std::max(max_kappa, kappa);
891 }
892 max_ratio_det_J_z =
893 std::max(max_ratio_det_J_z, max_det_J_z/min_det_J_z);
894 min_det_J = std::min(min_det_J, min_det_J_z);
895 max_det_J = std::max(max_det_J, max_det_J_z);
896 if (min_det_J_z <= 0.0)
897 {
898 if (nz < max_to_print)
899 {
900 Vector center;
901 mesh->GetElementCenter(i, center);
902 cout << "det(J) < 0 = " << min_det_J_z << " in element "
903 << i << ", centered at: ";
904 center.Print();
905 }
906 nz++;
907 bad_elems_by_geom[geom]++;
908 }
909 }
910 if (nz >= max_to_print)
911 {
912 cout << "det(J) < 0 for " << nz - max_to_print << " more elements "
913 << "not printed.\n";
914 }
915 cout << "\nbad elements = " << nz;
916 if (nz)
917 {
918 cout << " -- ";
919 Mesh::PrintElementsByGeometry(dim, bad_elems_by_geom, cout);
920 }
921 cout << "\nmin det(J) = " << min_det_J
922 << "\nmax det(J) = " << max_det_J
923 << "\nglobal ratio = " << max_det_J/min_det_J
924 << "\nmax el ratio = " << max_ratio_det_J_z
925 << "\nmin kappa = " << min_kappa
926 << "\nmax kappa = " << max_kappa << endl;
927 }
928
929 if (mk == 'f')
930 {
931 DenseMatrix point_mat(sdim,1);
932 cout << "\npoint in physical space ---> " << flush;
933 for (int i = 0; i < sdim; i++)
934 {
935 cin >> point_mat(i,0);
936 }
937 Array<int> elem_ids;
939
940 // physical -> reference space
941 mesh->FindPoints(point_mat, elem_ids, ips);
942
943 cout << "point in reference space:";
944 if (elem_ids[0] == -1)
945 {
946 cout << " NOT FOUND!\n";
947 }
948 else
949 {
950 cout << " element " << elem_ids[0] << ", ip =";
951 cout << " " << ips[0].x;
952 if (sdim > 1)
953 {
954 cout << " " << ips[0].y;
955 if (sdim > 2)
956 {
957 cout << " " << ips[0].z;
958 }
959 }
960 cout << endl;
961 }
962 }
963
964 if (mk == 'o')
965 {
966 cout << "What type of reordering?\n"
967 "g) Gecko edge-product minimization\n"
968 "h) Hilbert spatial sort\n"
969 "--> " << flush;
970 char rk;
971 cin >> rk;
972
973 Array<int> ordering, tentative;
974 if (rk == 'h')
975 {
976 mesh->GetHilbertElementOrdering(ordering);
977 mesh->ReorderElements(ordering);
978 }
979 else if (rk == 'g')
980 {
981 int outer, inner, window, period;
982 cout << "Enter number of outer iterations (default 5): " << flush;
983 cin >> outer;
984 cout << "Enter number of inner iterations (default 4): " << flush;
985 cin >> inner;
986 cout << "Enter window size (default 4, beware of exponential cost): "
987 << flush;
988 cin >> window;
989 cout << "Enter period for window size increment (default 2): "
990 << flush;
991 cin >> period;
992
993 real_t best_cost = infinity();
994 for (int i = 0; i < outer; i++)
995 {
996 int seed = i+1;
997 real_t cost = mesh->GetGeckoElementOrdering(
998 tentative, inner, window, period, seed, true);
999
1000 if (cost < best_cost)
1001 {
1002 ordering = tentative;
1003 best_cost = cost;
1004 }
1005 }
1006 cout << "Final cost: " << best_cost << endl;
1007
1008 mesh->ReorderElements(ordering);
1009 }
1010 }
1011
1012 // These are most of the cases that open a new GLVis window
1013 if (mk == 'm' || mk == 'b' || mk == 'e' || mk == 'v' || mk == 'h' ||
1014 mk == 'k' || mk == 'J' || mk == 'p' || mk == 'B' || mk == 'P')
1015 {
1016 FiniteElementSpace *bdr_attr_fespace = NULL;
1017 FiniteElementSpace *attr_fespace =
1018 new FiniteElementSpace(mesh, attr_fec);
1019 GridFunction bdr_attr;
1020 GridFunction attr(attr_fespace);
1021
1022 if (mk == 'm')
1023 {
1024 for (int i = 0; i < mesh->GetNE(); i++)
1025 {
1026 attr(i) = mesh->GetAttribute(i);
1027 }
1028 }
1029
1030 if (mk == 'P')
1031 {
1032 for (int i = 0; i < mesh->GetNE(); i++)
1033 {
1034 attr(i) = partitioning[i] + 1;
1035 }
1036 }
1037
1038 if (mk == 'b' || mk == 'B')
1039 {
1040 if (dim == 3)
1041 {
1042 delete bdr_mesh;
1043 bdr_mesh = skin_mesh(mesh);
1044 bdr_attr_fespace =
1045 new FiniteElementSpace(bdr_mesh, bdr_attr_fec);
1046 bdr_attr.SetSpace(bdr_attr_fespace);
1047 if (mk == 'b')
1048 {
1049 for (int i = 0; i < bdr_mesh->GetNE(); i++)
1050 {
1051 bdr_attr(i) = bdr_mesh->GetAttribute(i);
1052 }
1053 }
1054 else if (mk == 'B')
1055 {
1056 for (int i = 0; i < bdr_mesh->GetNE(); i++)
1057 {
1058 bdr_attr(i) = bdr_partitioning[i] + 1;
1059 }
1060 }
1061 else
1062 {
1063 MFEM_WARNING("Unimplemented case.");
1064 }
1065 }
1066 else
1067 {
1068 MFEM_WARNING("Unsupported mesh dimension.");
1069 attr = 1.0;
1070 }
1071 }
1072
1073 if (mk == 'v')
1074 {
1075 attr = 1.0;
1076 }
1077
1078 if (mk == 'e')
1079 {
1080 Array<int> coloring;
1081 srand(time(0));
1082 real_t a = rand_real();
1083 int el0 = (int)floor(a * mesh->GetNE());
1084 cout << "Generating coloring starting with element " << el0+1
1085 << " / " << mesh->GetNE() << endl;
1086 mesh->GetElementColoring(coloring, el0);
1087 for (int i = 0; i < coloring.Size(); i++)
1088 {
1089 attr(i) = coloring[i];
1090 }
1091 cout << "Number of colors: " << attr.Max() + 1 << endl;
1092 for (int i = 0; i < mesh->GetNE(); i++)
1093 {
1094 attr(i) = elem_partitioning[i] = i; // coloring by element number
1095 }
1096 cout << "GLVis keystrokes for mesh element visualization:\n"
1097 << "- F3/F4 - Shrink/Zoom the elements\n"
1098 << "- Ctrl+F3/F4 - 3D: cut holes in element faces \n"
1099 << "- F8 - 3D: toggle visible elements\n"
1100 << "- F9/F10 - 3D: cycle through visible elements\n";
1101 }
1102
1103 if (mk == 'h')
1104 {
1105 DenseMatrix J(dim);
1106 real_t h_min, h_max;
1107 h_min = infinity();
1108 h_max = -h_min;
1109 for (int i = 0; i < mesh->GetNE(); i++)
1110 {
1111 Geometry::Type geom = mesh->GetElementBaseGeometry(i);
1113 T->SetIntPoint(&Geometries.GetCenter(geom));
1114 Geometries.JacToPerfJac(geom, T->Jacobian(), J);
1115
1116 attr(i) = J.Det();
1117 if (attr(i) < 0.0)
1118 {
1119 attr(i) = -pow(-attr(i), 1.0/real_t(dim));
1120 }
1121 else
1122 {
1123 attr(i) = pow(attr(i), 1.0/real_t(dim));
1124 }
1125 h_min = min(h_min, attr(i));
1126 h_max = max(h_max, attr(i));
1127 }
1128 cout << "h_min = " << h_min << ", h_max = " << h_max << endl;
1129 }
1130
1131 if (mk == 'k')
1132 {
1133 DenseMatrix J(dim);
1134 for (int i = 0; i < mesh->GetNE(); i++)
1135 {
1136 Geometry::Type geom = mesh->GetElementBaseGeometry(i);
1138 T->SetIntPoint(&Geometries.GetCenter(geom));
1139 Geometries.JacToPerfJac(geom, T->Jacobian(), J);
1140 attr(i) = J.CalcSingularvalue(0) / J.CalcSingularvalue(dim-1);
1141 }
1142 }
1143
1144 if (mk == 'J')
1145 {
1146 // The "scaled Jacobian" is the determinant of the Jacobian scaled
1147 // by the l2 norms of its columns. It can be used to identify badly
1148 // skewed elements, since it takes values between 0 and 1, with 0
1149 // corresponding to a flat element, and 1 to orthogonal columns.
1150 DenseMatrix J(dim);
1151 int sd;
1152 cout << "subdivision factor ---> " << flush;
1153 cin >> sd;
1154 for (int i = 0; i < mesh->GetNE(); i++)
1155 {
1156 Geometry::Type geom = mesh->GetElementBaseGeometry(i);
1158
1159 RefinedGeometry *RefG = GlobGeometryRefiner.Refine(geom, sd, 1);
1160 IntegrationRule &ir = RefG->RefPts;
1161
1162 // For each element, find the minimal scaled Jacobian in a
1163 // lattice of points with the given subdivision factor.
1164 attr(i) = infinity();
1165 for (int j = 0; j < ir.GetNPoints(); j++)
1166 {
1167 T->SetIntPoint(&ir.IntPoint(j));
1168 Geometries.JacToPerfJac(geom, T->Jacobian(), J);
1169
1170 // Jacobian determinant
1171 real_t sJ = J.Det();
1172
1173 for (int k = 0; k < J.Width(); k++)
1174 {
1175 Vector col;
1176 J.GetColumnReference(k,col);
1177 // Scale by column norms
1178 sJ /= col.Norml2();
1179 }
1180
1181 attr(i) = std::min(sJ, attr(i));
1182 }
1183 }
1184 }
1185
1186 if (mk == 'p')
1187 {
1188 cout << "What type of partitioning?\n"
1189 "c) Cartesian\n"
1190 "s) Simple 1D split of the element sequence\n"
1191 "0) METIS_PartGraphRecursive (sorted neighbor lists)\n"
1192 "1) METIS_PartGraphKway (sorted neighbor lists)"
1193 " (default)\n"
1194 "2) METIS_PartGraphVKway (sorted neighbor lists)\n"
1195 "3) METIS_PartGraphRecursive\n"
1196 "4) METIS_PartGraphKway\n"
1197 "5) METIS_PartGraphVKway\n"
1198 "--> " << flush;
1199 char pk;
1200 cin >> pk;
1201 if (pk == 'c')
1202 {
1203 int nxyz[3];
1204 cout << "Enter nx: " << flush;
1205 cin >> nxyz[0]; np = nxyz[0];
1206 if (mesh->Dimension() > 1)
1207 {
1208 cout << "Enter ny: " << flush;
1209 cin >> nxyz[1]; np *= nxyz[1];
1210 if (mesh->Dimension() > 2)
1211 {
1212 cout << "Enter nz: " << flush;
1213 cin >> nxyz[2]; np *= nxyz[2];
1214 }
1215 }
1216 int *part = mesh->CartesianPartitioning(nxyz);
1217 partitioning = Array<int>(part, mesh->GetNE());
1218 delete [] part;
1219 recover_bdr_partitioning(mesh, partitioning, bdr_partitioning);
1220 }
1221 else if (pk == 's')
1222 {
1223 cout << "Enter number of processors: " << flush;
1224 cin >> np;
1225
1226 partitioning.SetSize(mesh->GetNE());
1227 for (int i = 0; i < mesh->GetNE(); i++)
1228 {
1229 partitioning[i] = (long long)i * np / mesh->GetNE();
1230 }
1231 recover_bdr_partitioning(mesh, partitioning, bdr_partitioning);
1232 }
1233 else
1234 {
1235 int part_method = pk - '0';
1236 if (part_method < 0 || part_method > 5)
1237 {
1238 continue;
1239 }
1240 cout << "Enter number of processors: " << flush;
1241 cin >> np;
1242 int *part = mesh->GeneratePartitioning(np, part_method);
1243 partitioning = Array<int>(part, mesh->GetNE());
1244 delete [] part;
1245 recover_bdr_partitioning(mesh, partitioning, bdr_partitioning);
1246 }
1247 if (partitioning)
1248 {
1249 const char part_file[] = "partitioning.txt";
1250 ofstream opart(part_file);
1251 opart << "number_of_elements " << mesh->GetNE() << '\n'
1252 << "number_of_processors " << np << '\n';
1253 for (int i = 0; i < mesh->GetNE(); i++)
1254 {
1255 opart << partitioning[i] << '\n';
1256 }
1257 cout << "Partitioning file: " << part_file << endl;
1258
1259 Array<int> proc_el(np);
1260 proc_el = 0;
1261 for (int i = 0; i < mesh->GetNE(); i++)
1262 {
1263 proc_el[partitioning[i]]++;
1264 }
1265 int min_el = proc_el[0], max_el = proc_el[0];
1266 for (int i = 1; i < np; i++)
1267 {
1268 if (min_el > proc_el[i])
1269 {
1270 min_el = proc_el[i];
1271 }
1272 if (max_el < proc_el[i])
1273 {
1274 max_el = proc_el[i];
1275 }
1276 }
1277 cout << "Partitioning stats:\n"
1278 << " "
1279 << setw(12) << "minimum"
1280 << setw(12) << "average"
1281 << setw(12) << "maximum"
1282 << setw(12) << "total" << '\n';
1283 cout << " elements "
1284 << setw(12) << min_el
1285 << setw(12) << real_t(mesh->GetNE())/np
1286 << setw(12) << max_el
1287 << setw(12) << mesh->GetNE() << endl;
1288 }
1289 else
1290 {
1291 continue;
1292 }
1293
1294 for (int i = 0; i < mesh->GetNE(); i++)
1295 {
1296 attr(i) = partitioning[i] + 1;
1297 }
1298 }
1299
1300 char vishost[] = "localhost";
1301 socketstream sol_sock(vishost, visport);
1302 if (sol_sock.is_open())
1303 {
1304 sol_sock.precision(14);
1305 if (sdim == 2)
1306 {
1307 sol_sock << "fem2d_gf_data_keys\n";
1308 if (mk != 'p')
1309 {
1310 mesh->Print(sol_sock);
1311 }
1312 else
1313 {
1314 // NURBS meshes do not support PrintWithPartitioning
1315 if (mesh->NURBSext)
1316 {
1317 mesh->Print(sol_sock);
1318 for (int i = 0; i < mesh->GetNE(); i++)
1319 {
1320 attr(i) = partitioning[i];
1321 }
1322 }
1323 else
1324 {
1325 if (mk == 'e')
1326 {
1327 mesh->PrintWithPartitioning(elem_partitioning, sol_sock, 1);
1328 }
1329 else
1330 {
1331 mesh->PrintWithPartitioning(partitioning, sol_sock, 1);
1332 }
1333 }
1334 }
1335 attr.Save(sol_sock);
1336 sol_sock << "RjlmAb***********";
1337 if (mk == 'v')
1338 {
1339 sol_sock << "e";
1340 }
1341 else
1342 {
1343 sol_sock << "\n";
1344 }
1345 }
1346 else // sdim == 3
1347 {
1348 sol_sock << "fem3d_gf_data_keys\n";
1349 if (mk == 'v' || mk == 'h' || mk == 'k' || mk == 'J' || mk == 'm')
1350 {
1351 mesh->Print(sol_sock);
1352 }
1353 else if (mk == 'b' || mk == 'B')
1354 {
1355 bdr_mesh->Print(sol_sock);
1356 bdr_attr.Save(sol_sock);
1357 sol_sock << "mcaaA";
1358 // Switch to a discrete color scale
1359 sol_sock << "pppppp" << "pppppp" << "pppppp";
1360 }
1361 else
1362 {
1363 // NURBS meshes do not support PrintWithPartitioning
1364 if (mesh->NURBSext)
1365 {
1366 mesh->Print(sol_sock);
1367 for (int i = 0; i < mesh->GetNE(); i++)
1368 {
1369 attr(i) = partitioning[i];
1370 }
1371 }
1372 else
1373 {
1374 if (mk == 'e')
1375 {
1376 mesh->PrintWithPartitioning(elem_partitioning, sol_sock, 1);
1377 }
1378 else
1379 {
1380 mesh->PrintWithPartitioning(partitioning, sol_sock, 1);
1381 }
1382 }
1383 }
1384 if (mk != 'b' && mk != 'B')
1385 {
1386 attr.Save(sol_sock);
1387 sol_sock << "maaA";
1388 if (mk == 'v')
1389 {
1390 sol_sock << "aa";
1391 }
1392 else
1393 {
1394 sol_sock << "\n";
1395 }
1396 }
1397 }
1398 sol_sock << flush;
1399 }
1400 else
1401 {
1402 cout << "Unable to connect to "
1403 << vishost << ':' << visport << endl;
1404 }
1405 delete attr_fespace;
1406 delete bdr_attr_fespace;
1407 }
1408
1409 if (mk == 'l')
1410 {
1411 // Project and plot the function 'f'
1412 int p;
1413 FiniteElementCollection *fec = NULL;
1414 cout << "Enter projection space order: " << flush;
1415 cin >> p;
1416 if (p >= 1)
1417 {
1418 fec = new H1_FECollection(p, mesh->Dimension(),
1420 }
1421 else
1422 {
1423 fec = new DG_FECollection(-p, mesh->Dimension(),
1425 }
1426 FiniteElementSpace fes(mesh, fec);
1427 GridFunction level(&fes);
1428 FunctionCoefficient coeff(f);
1429 level.ProjectCoefficient(coeff);
1430 char vishost[] = "localhost";
1431 socketstream sol_sock(vishost, visport);
1432 if (sol_sock.is_open())
1433 {
1434 sol_sock.precision(14);
1435 sol_sock << "solution\n" << *mesh << level << flush;
1436 }
1437 else
1438 {
1439 cout << "Unable to connect to "
1440 << vishost << ':' << visport << endl;
1441 }
1442 delete fec;
1443 }
1444
1445 if (mk == 'S')
1446 {
1447 const char omesh_file[] = "mesh-explorer.mesh";
1448 ofstream omesh(omesh_file);
1449 omesh.precision(14);
1450 mesh->Print(omesh);
1451 cout << "New mesh file: " << omesh_file << endl;
1452 }
1453
1454 if (mk == 'T')
1455 {
1456 string mesh_prefix("mesh-explorer.mesh."), line;
1457 MeshPartitioner partitioner(*mesh, np, partitioning);
1458 MeshPart mesh_part;
1459 cout << "Enter mesh file prefix or press <enter> to use \""
1460 << mesh_prefix << "\": " << flush;
1461 // extract and ignore all characters after 'T' up to and including the
1462 // new line:
1463 cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
1464 getline(cin, line);
1465 if (!line.empty()) { mesh_prefix = line; }
1466 int precision;
1467 cout << "Enter floating point output precision (num. digits): "
1468 << flush;
1469 cin >> precision;
1470 for (int i = 0; i < np; i++)
1471 {
1472 partitioner.ExtractPart(i, mesh_part);
1473
1474 ofstream omesh(MakeParFilename(mesh_prefix, i));
1475 omesh.precision(precision);
1476 mesh_part.Print(omesh);
1477 }
1478 cout << "New parallel mesh files: " << mesh_prefix << "<rank>" << endl;
1479 }
1480
1481 if (mk == 'V')
1482 {
1483 const char omesh_file[] = "mesh-explorer.vtk";
1484 ofstream omesh(omesh_file);
1485 omesh.precision(14);
1486 mesh->PrintVTK(omesh);
1487 cout << "New VTK mesh file: " << omesh_file << endl;
1488 }
1489
1490#ifdef MFEM_USE_NETCDF
1491 if (mk == 'X')
1492 {
1493 const char omesh_file[] = "mesh-explorer.e";
1494 mesh->PrintExodusII(omesh_file);
1495 cout << "New Exodus II mesh file: " << omesh_file << endl;
1496 }
1497#endif
1498
1499 if (mk == 'D')
1500 {
1501 cout << "What type of DataCollection?\n"
1502 "p) ParaView Data Collection\n"
1503 "v) VisIt Data Collection\n"
1504 "--> " << flush;
1505 char dk;
1506 cin >> dk;
1507 if (dk == 'p' || dk == 'P')
1508 {
1509 const char omesh_file[] = "mesh-explorer-paraview";
1510 ParaViewDataCollection dc(omesh_file, mesh);
1511 if (mesh->GetNodes())
1512 {
1513 int order = mesh->GetNodes()->FESpace()->GetMaxElementOrder();
1514 if (order > 1)
1515 {
1516 dc.SetHighOrderOutput(true);
1517 dc.SetLevelsOfDetail(order);
1518 }
1519 }
1520 dc.Save();
1521 cout << "New ParaView mesh file: " << omesh_file << endl;
1522 }
1523 else if (dk == 'v' || dk == 'V')
1524 {
1525 const char omesh_file[] = "mesh-explorer-visit";
1526 VisItDataCollection dc(omesh_file, mesh);
1527 dc.SetPrecision(14);
1528 dc.Save();
1529 cout << "New VisIt mesh file: " << omesh_file << "_000000.mfem_root"
1530 << endl;
1531 }
1532 else
1533 {
1534 cout << "Unrecognized DataCollection type: \"" << dk << "\""
1535 << endl;
1536 }
1537 }
1538
1539#ifdef MFEM_USE_ZLIB
1540 if (mk == 'Z')
1541 {
1542 const char omesh_file[] = "mesh-explorer.mesh.gz";
1543 ofgzstream omesh(omesh_file, "zwb9");
1544 omesh.precision(14);
1545 mesh->Print(omesh);
1546 cout << "New mesh file: " << omesh_file << endl;
1547 }
1548#endif
1549
1550 }
1551
1552 delete bdr_attr_fec;
1553 delete attr_fec;
1554 delete bdr_mesh;
1555 delete mesh;
1556 return 0;
1557}
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:840
int Size() const
Return the logical size of the array.
Definition array.hpp:166
void DeleteAll()
Delete the whole array.
Definition array.hpp:1033
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:912
@ GaussLobatto
Closed type.
Definition fe_base.hpp:36
@ GaussLegendre
Open type.
Definition fe_base.hpp:35
@ ClosedUniform
Nodes: x_i = i/(n-1), i=0,...,n-1.
Definition fe_base.hpp:39
Piecewise-constant discontinuous finite elements in 2D. This class is kept only for backward compatib...
Definition fe_coll.hpp:1112
Piecewise-constant discontinuous finite elements in 3D. This class is kept only for backward compatib...
Definition fe_coll.hpp:1303
void SetPrecision(int prec)
Set the precision (number of digits) used for the text output of doubles.
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
void GetColumnReference(int c, Vector &col)
Definition densemat.hpp:331
real_t CalcSingularvalue(const int i) const
Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
real_t Det() const
Definition densemat.cpp:496
const DenseMatrix & Jacobian()
Return the Jacobian matrix of the transformation at the currently set IntegrationPoint,...
Definition eltrans.hpp:132
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition eltrans.hpp:106
Abstract data type element.
Definition element.hpp:29
Geometry::Type GetGeometryType() const
Definition element.hpp:55
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
int GetAttribute() const
Return element's attribute.
Definition element.hpp:58
virtual int GetNVertices() const =0
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name.
Definition fe_coll.cpp:124
virtual const char * Name() const
Definition fe_coll.hpp:79
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:208
DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element 'elem'. The returned indices are offsets into an ldo...
Definition fespace.cpp:3502
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Definition fespace.hpp:823
int GetNBE() const
Returns number of boundary elements in the mesh.
Definition fespace.hpp:878
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
Definition fespace.cpp:304
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:869
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:856
virtual int GetMaxElementOrder() const
Return the maximum polynomial order over all elements.
Definition fespace.hpp:674
DofTransformation * GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for i'th boundary element. The returned indices are offsets int...
Definition fespace.cpp:319
int DofToVDof(int dof, int vd, int ndofs=-1) const
Compute a single vdof corresponding to the index dof and the vector index vd.
Definition fespace.cpp:266
A general function coefficient.
RefinedGeometry * Refine(Geometry::Type Geom, int Times, int ETimes=1)
Definition geom.cpp:1136
static const int NumGeom
Definition geom.hpp:46
const IntegrationPoint & GetCenter(int GeomType) const
Return the center of the given Geometry::Type, GeomType.
Definition geom.hpp:75
void JacToPerfJac(int GeomType, const DenseMatrix &J, DenseMatrix &PJ) const
Definition geom.cpp:909
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:32
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
void MakeOwner(FiniteElementCollection *fec_)
Make the GridFunction the owner of fec_owned and fes.
Definition gridfunc.hpp:123
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
virtual void SetSpace(FiniteElementSpace *f)
Associate a new FiniteElementSpace with the GridFunction.
Definition gridfunc.cpp:226
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:279
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:100
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:256
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:259
A standard isoparametric element transformation.
Definition eltrans.hpp:629
const DenseMatrix & GetPointMat() const
Return the stored point matrix.
Definition eltrans.hpp:671
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:350
Class containing a minimal description of a part (a subset of the elements) of a Mesh and its connect...
Definition mesh.hpp:2765
void Print(std::ostream &os) const
Write the MeshPart to a stream using the parallel format "MFEM mesh v1.2".
Definition mesh.cpp:14057
Class that allows serial meshes to be partitioned into MeshPart objects, typically one MeshPart at a ...
Definition mesh.hpp:2993
void ExtractPart(int part_id, MeshPart &mesh_part) const
Construct a MeshPart corresponding to the given part_id.
Definition mesh.cpp:14392
Mesh data type.
Definition mesh.hpp:65
void NURBSCoarsening(int cf=2, real_t tol=1.0e-12)
Definition mesh.cpp:11169
int AddSegment(int v1, int v2, int attr=1)
Adds a segment to the mesh given by 2 vertices v1 and v2.
Definition mesh.cpp:2057
void GetElementColoring(Array< int > &colors, int el0=0)
Definition mesh.cpp:12766
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:304
NURBSExtension * NURBSext
Optional NURBS mesh extension.
Definition mesh.hpp:312
int * CartesianPartitioning(int nxyz[])
Definition mesh.cpp:8705
void GeneralRefinement(const Array< Refinement > &refinements, int nonconforming=-1, int nc_limit=0)
Definition mesh.cpp:11225
int GetAttribute(int i) const
Return the attribute of element i.
Definition mesh.hpp:1484
int AddQuad(int v1, int v2, int v3, int v4, int attr=1)
Adds a quadrilateral to the mesh given by 4 vertices v1 through v4.
Definition mesh.cpp:2085
const FiniteElementSpace * GetNodalFESpace() const
Definition mesh.cpp:6794
void PrintCharacteristics(Vector *Vh=NULL, Vector *Vk=NULL, std::ostream &os=mfem::out)
Compute and print mesh characteristics such as number of vertices, number of elements,...
Definition mesh.cpp:254
int AddTriangle(int v1, int v2, int v3, int attr=1)
Adds a triangle to the mesh given by 3 vertices v1 through v3.
Definition mesh.cpp:2071
real_t GetGeckoElementOrdering(Array< int > &ordering, int iterations=4, int window=4, int period=2, int seed=0, bool verbose=false, real_t time_limit=0)
Definition mesh.cpp:2593
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
Definition mesh.cpp:3502
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
Print the mesh to the given stream using the default MFEM mesh format.
Definition mesh.hpp:2567
void PrintWithPartitioning(int *partitioning, std::ostream &os, int elem_attr=0) const
Prints the mesh with boundary elements given by the boundary of the subdomains, so that the boundary ...
Definition mesh.cpp:12841
int AddVertex(real_t x, real_t y=0.0, real_t z=0.0)
Definition mesh.cpp:2000
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1377
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1306
void RandomRefinement(real_t prob, bool aniso=false, int nonconforming=-1, int nc_limit=0)
Refine each element with given probability. Uses GeneralRefinement.
Definition mesh.cpp:11317
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
Definition mesh.hpp:1449
void ReorderElements(const Array< int > &ordering, bool reorder_vertices=true)
Definition mesh.cpp:2812
void Transform(std::function< void(const Vector &, Vector &)> f)
Definition mesh.cpp:13540
static Mesh MakeRefined(Mesh &orig_mesh, int ref_factor, int ref_type)
Create a refined (by any factor) version of orig_mesh.
Definition mesh.cpp:4664
real_t GetElementSize(int i, int type=0)
Get the size of the i-th element relative to the perfect reference element.
Definition mesh.cpp:110
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
Definition mesh.cpp:360
void PrintExodusII(const std::string &fpath)
Export a mesh to an Exodus II file.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1309
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9627
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
Definition mesh.hpp:1374
void GetHilbertElementOrdering(Array< int > &ordering)
Definition mesh.cpp:2760
void GetBdrElementAdjacentElement(int bdr_el, int &el, int &info) const
For the given boundary element, bdr_el, return its adjacent element and its info, i....
Definition mesh.cpp:7905
void GetElementCenter(int i, Vector &center)
Definition mesh.cpp:80
static void PrintElementsByGeometry(int dim, const Array< int > &num_elems_by_geom, std::ostream &os)
Auxiliary method used by PrintCharacteristics().
Definition mesh.cpp:240
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1380
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
Definition mesh.cpp:3608
virtual int FindPoints(DenseMatrix &point_mat, Array< int > &elem_ids, Array< IntegrationPoint > &ips, bool warn=true, InverseElementTransformation *inv_trans=NULL)
Find the ids of the elements that contain the given points, and their corresponding reference coordin...
Definition mesh.cpp:13800
void NewNodes(GridFunction &nodes, bool make_owner=false)
Replace the internal node GridFunction with the given GridFunction.
Definition mesh.cpp:9654
virtual void NURBSUniformRefinement(int rf=2, real_t tol=1.0e-12)
Refine NURBS mesh, with an optional refinement factor, generally anisotropic.
Definition mesh.cpp:6320
void EnsureNCMesh(bool simplices_nonconforming=false)
Definition mesh.cpp:11293
void PrintVTK(std::ostream &os)
Definition mesh.cpp:12192
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Set the curvature of the mesh nodes using the given polynomial degree.
Definition mesh.cpp:6799
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11637
Geometry::Type GetElementBaseGeometry(int i) const
Definition mesh.hpp:1556
virtual void RefineNURBSWithKVFactors(int rf, const std::string &kvf)
Definition mesh.cpp:6315
int * GeneratePartitioning(int nparts, int part_method=1)
Definition mesh.cpp:8749
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition mesh.hpp:302
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
Definition mesh.hpp:1416
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:72
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void PrintOptions(std::ostream &out) const
Print the options.
void PrintHelp(std::ostream &out) const
Print the help message.
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
Definition optparser.hpp:82
bool Good() const
Return true if the command line options were parsed successfully.
bool Help() const
Return true if we are flagged to print the help message.
void PrintError(std::ostream &out) const
Print the error message.
void SetLevelsOfDetail(int levels_of_detail_)
Set the refinement level.
void SetHighOrderOutput(bool high_order_output_)
Sets whether or not to output the data as high-order elements (false by default).
Writer for ParaView visualization (PVD and VTU format)
IntegrationRule RefPts
Definition geom.hpp:321
Vector data type.
Definition vector.hpp:82
void Randomize(int seed=0)
Set random values in the vector.
Definition vector.cpp:955
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
Definition vector.cpp:870
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
Definition vector.cpp:702
real_t Norml2() const
Returns the l2 norm of the vector.
Definition vector.cpp:968
real_t Max() const
Returns the maximal element of the vector.
Definition vector.cpp:1200
Data collection with VisIt I/O routines.
void Save() override
Save the collection and a VisIt root file.
bool is_open()
True if the socketstream is open, false otherwise.
const real_t alpha
Definition ex15.cpp:369
real_t kappa
Definition ex24.cpp:54
int dim
Definition ex24.cpp:53
int main()
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
Mesh * skin_mesh(Mesh *mesh)
real_t f(const Vector &p)
real_t region_eps
Mesh * read_par_mesh(int np, const char *mesh_prefix, Array< int > &partitioning, Array< int > &bdr_partitioning)
void transformation(const Vector &p, Vector &v)
void recover_bdr_partitioning(const Mesh *mesh, const Array< int > &partitioning, Array< int > &bdr_partitioning)
real_t region(const Vector &p)
real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition vector.hpp:47
std::string MakeParFilename(const std::string &prefix, const int myid, const std::string suffix, const int width)
Construct a string of the form "<prefix><myid><suffix>" where the integer myid is padded with leading...
Definition globals.cpp:48
GeometryRefiner GlobGeometryRefiner
Definition geom.cpp:2014
Geometry Geometries
Definition fe.cpp:49
real_t rand_real()
Generate a random real_t number in the interval [0,1) using rand().
Definition vector.hpp:61
L2_FECollection DG_FECollection
Declare an alternative name for L2_FECollection = DG_FECollection.
Definition fe_coll.hpp:403
float real_t
Definition config.hpp:46
const char vishost[]
real_t p(const Vector &x, real_t t)
std::array< int, NCMesh::MaxFaceNodes > nodes