From 8ac14edb9a08cf63385c5a88afc314c8accee1fe Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Thu, 11 Jul 2024 15:19:41 -0500 Subject: [PATCH 01/11] BoundingBox print and iostreams support --- include/geom/bounding_box.h | 19 +++++++++++++++++++ src/geom/bounding_box.C | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/include/geom/bounding_box.h b/include/geom/bounding_box.h index 4c8f44355d8..81af4c9cd38 100644 --- a/include/geom/bounding_box.h +++ b/include/geom/bounding_box.h @@ -151,6 +151,25 @@ class BoundingBox : public std::pair * constructor and by invalidate(). */ void scale(const Real factor); + + /** + * Formatted print, by default to \p libMesh::out. + */ + void print(std::ostream & os = libMesh::out) const; + + /** + * Formatted print as above but supports the syntax: + * + * \code + * BoundingBox b; + * std::cout << b << std::endl; + * \endcode + */ + friend std::ostream & operator << (std::ostream & os, const BoundingBox & b) + { + b.print(os); + return os; + } }; diff --git a/src/geom/bounding_box.C b/src/geom/bounding_box.C index f5620b4d575..c1978f9c4c4 100644 --- a/src/geom/bounding_box.C +++ b/src/geom/bounding_box.C @@ -150,4 +150,10 @@ void BoundingBox::scale(const Real factor) } } + +void BoundingBox::print(std::ostream & os) const +{ + os << "(min=" << this->min() << ", max=" << this->max() << ")"; +} + } // namespace libMesh From 5a5ba3bad3f86dbfe1042fd1cf0bb08c757a243f Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Thu, 11 Jul 2024 15:20:31 -0500 Subject: [PATCH 02/11] Entities BoundingBox testing in GmshIO Right now we ignore the point locations and the curve/surface/volume bounding box extents in a GMSH $Entities section; this led to unexpected behavior in #3899 Let's insist that those locations and bounding boxes are accurate. False positives for these tests are an easy fix (edit the $Entities), whereas missed true positives lead to erroneous simulations. --- src/mesh/gmsh_io.C | 75 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/src/mesh/gmsh_io.C b/src/mesh/gmsh_io.C index 6baa7986594..70937756ffc 100644 --- a/src/mesh/gmsh_io.C +++ b/src/mesh/gmsh_io.C @@ -19,6 +19,7 @@ #include "libmesh/libmesh_config.h" #include "libmesh/libmesh_logging.h" #include "libmesh/boundary_info.h" +#include "libmesh/bounding_box.h" #include "libmesh/elem.h" #include "libmesh/gmsh_io.h" #include "libmesh/mesh_base.h" @@ -192,6 +193,9 @@ void GmshIO::read_mesh(std::istream & in) // the entity tag/id std::map, int> entity_to_physical_id; + // Map from entities to bounding boxes. The key is the same. + std::map, BoundingBox> entity_to_bounding_box; + // For reading the file line by line std::string s; @@ -299,6 +303,9 @@ void GmshIO::read_mesh(std::istream & in) "Sorry, you cannot currently specify multiple subdomain or " "boundary ids for a given geometric entity"); + entity_to_bounding_box[std::make_pair(0, point_tag)] = + BoundingBox(Point(x,y,z),Point(x,y,z)); + if (num_physical_tags) { in >> physical_tag; @@ -316,6 +323,9 @@ void GmshIO::read_mesh(std::istream & in) "I don't believe that we can specify multiple subdomain or " "boundary ids for a given geometric entity"); + entity_to_bounding_box[std::make_pair(1, curve_tag)] = + BoundingBox(Point(minx,miny,minz),Point(maxx,maxy,maxz)); + if (num_physical_tags) { in >> physical_tag; @@ -336,6 +346,9 @@ void GmshIO::read_mesh(std::istream & in) "I don't believe that we can specify multiple subdomain or " "boundary ids for a given geometric entity"); + entity_to_bounding_box[std::make_pair(2, surface_tag)] = + BoundingBox(Point(minx,miny,minz),Point(maxx,maxy,maxz)); + if (num_physical_tags) { in >> physical_tag; @@ -356,6 +369,9 @@ void GmshIO::read_mesh(std::istream & in) "I don't believe that we can specify multiple subdomain or " "boundary ids for a given geometric entity"); + entity_to_bounding_box[std::make_pair(3, volume_tag)] = + BoundingBox(Point(minx,miny,minz),Point(maxx,maxy,maxz)); + if (num_physical_tags) { in >> physical_tag; @@ -625,19 +641,47 @@ void GmshIO::read_mesh(std::istream & in) std::size_t gmsh_element_id; in >> gmsh_element_id; + // Make sure this element isn't somewhere + // unexpected + + // A default bounding box is [inf,-inf] (empty); + // swap that and we get [-inf,inf] (everything) + BoundingBox expected_bounding_box; + std::swap(expected_bounding_box.min(), + expected_bounding_box.max()); + + if (auto it = entity_to_bounding_box.find + (std::make_pair(entity_dim, entity_tag)); + it != entity_to_bounding_box.end()) + expected_bounding_box = it->second; + // Get the remainder of the line that includes the nodes ids std::getline(in, s); std::istringstream is(s); std::size_t local_node_counter = 0, gmsh_node_id; while (is >> gmsh_node_id) { + Node * node = mesh.node_ptr(nodetrans[gmsh_node_id]); + + // Make sure the file is consistent about entity + // placement + libmesh_error_msg_if + (!expected_bounding_box.contains_point(*node), + "$Elements dim " << entity_dim << " element " + << gmsh_element_id << " (entity " << entity_tag + << ", " << + Utility::enum_to_string(eletype.type) << + ") has node at " << *static_cast(node) + << "\n outside entity physical bounding box " << + expected_bounding_box); + // Add node pointers to the elements. // If there is a node translation table, use it. if (eletype.nodes.size() > 0) elem->set_node(eletype.nodes[local_node_counter++]) = - mesh.node_ptr(nodetrans[gmsh_node_id]); + node; else - elem->set_node(local_node_counter++) = mesh.node_ptr(nodetrans[gmsh_node_id]); + elem->set_node(local_node_counter++) = node; } // Make sure that the libmesh element we added has nnodes nodes. @@ -665,8 +709,33 @@ void GmshIO::read_mesh(std::istream & in) std::size_t gmsh_element_id, gmsh_node_id; in >> gmsh_element_id; in >> gmsh_node_id; + + // Make sure the file is consistent about entity + // placement + + // A default bounding box is [inf,-inf] (empty); + // swap that and we get [-inf,inf] (everything) + BoundingBox expected_bounding_box; + std::swap(expected_bounding_box.min(), + expected_bounding_box.max()); + + if (auto it = entity_to_bounding_box.find + (std::make_pair(entity_dim, entity_tag)); + it != entity_to_bounding_box.end()) + expected_bounding_box = it->second; + + Node * node = mesh.node_ptr(nodetrans[gmsh_node_id]); + + libmesh_error_msg_if + (!expected_bounding_box.contains_point(*node), + "$Elements dim " << entity_dim << " element " + << gmsh_element_id << " (entity " << entity_tag << + ") has node at " << *static_cast(node) + << "\n outside entity physical bounding box " << + expected_bounding_box); + mesh.get_boundary_info().add_node( - nodetrans[gmsh_node_id], + node, static_cast(entity_to_physical_id[ std::make_pair(entity_dim, entity_tag)])); } // end for (loop over elements in entity block) From 1802440bc48775f0273a7f9eb3d7c7f09a544e83 Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Thu, 11 Jul 2024 15:24:10 -0500 Subject: [PATCH 03/11] Unit test for new Gmsh error testing --- tests/Makefile.am | 1 + tests/mesh/mesh_input.C | 32 ++++++ tests/meshes/block.msh | 215 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 248 insertions(+) create mode 100644 tests/meshes/block.msh diff --git a/tests/Makefile.am b/tests/Makefile.am index 996a2723ec6..2a0bd0985e8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -153,6 +153,7 @@ data = matrices/geom_1_extraction_op.m \ meshes/1_quad.bxt.gz \ meshes/25_quad.bxt.gz \ meshes/bad_64bit_elem_integers.e \ + meshes/block.msh \ meshes/BlockWithHole_Patch9.bxt.gz \ meshes/constrain10to4.m \ meshes/Cube_With_Sidesets.e \ diff --git a/tests/mesh/mesh_input.C b/tests/mesh/mesh_input.C index b135b828605..ea934745c0d 100644 --- a/tests/mesh/mesh_input.C +++ b/tests/mesh/mesh_input.C @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include "test_comm.h" #include "libmesh_cppunit.h" +#include using namespace libMesh; @@ -190,6 +192,10 @@ public: CPPUNIT_TEST( testDynaFileMappingsCyl3d); #endif // LIBMESH_HAVE_GZSTREAM #endif // LIBMESH_DIM > 1 + // +#if LIBMESH_DIM > 1 + CPPUNIT_TEST( testGmsh ); +#endif #ifdef LIBMESH_HAVE_TETGEN CPPUNIT_TEST( testTetgenIO ); @@ -1508,6 +1514,32 @@ public: helperTestingDynaQuad(mesh); } + void testGmsh () + { + LOG_UNIT_TEST; + + Mesh mesh(*TestCommWorld); + + GmshIO gmsh_io(mesh); + +#ifdef LIBMESH_ENABLE_EXCEPTIONS + std::string what = ""; + try + { + if (mesh.processor_id() == 0) + gmsh_io.read("meshes/block.msh"); + } + catch (libMesh::LogicError & e) + { + what = e.what(); + } + + TestCommWorld->broadcast(what); + std::regex msg_regex("outside entity physical bounding box"); + CPPUNIT_ASSERT(std::regex_search(what, msg_regex)); +#endif + } + void testTetgenIO () { #ifdef LIBMESH_HAVE_TETGEN diff --git a/tests/meshes/block.msh b/tests/meshes/block.msh new file mode 100644 index 00000000000..9ad5c63b867 --- /dev/null +++ b/tests/meshes/block.msh @@ -0,0 +1,215 @@ +$MeshFormat +4.1 0 8 +$EndMeshFormat +$PhysicalNames +18 +0 1 "PointC" +0 2 "PointA" +0 3 "PointB" +1 4 "lineBeamA" lower_dimensional_block +1 5 "lineBeamB" lower_dimensional_block +3 6 "Base" +2 7 "PlateA" lower_dimensional_block +2 8 "Base_YMin_0" +2 9 "Base_XMin_0" +2 10 "Base_XMax_0" +2 11 "Base_YMax_0" +2 12 "Base_ZMin_0" +2 13 "BoundaryXMin" +2 14 "BoundaryXMax" +2 15 "BoundaryYMin" +2 16 "BoundaryYMax" +2 17 "BoundaryZMin" +2 18 "BoundaryZMax" +$EndPhysicalNames +$Entities +3 2 12 1 +1 0 0 -14 1 1 +2 14 0 -14 1 2 +3 -14 15 -14 1 3 +1 -14 -10 -14 0 0 -14 1 4 0 +2 -14 0 -14 0 15 -14 1 5 0 +1 -14 -10 -14 0 0 -14 1 7 0 +2 -14 -10 -17 14 -10 -14 1 8 0 +3 -14 -10 -17 -14 15 -14 1 9 0 +4 14 -10 -17 14 15 -14 1 10 0 +5 -14 15 -17 14 15 -14 1 11 0 +6 -14 -10 -17 14 15 -17 1 12 0 +7 -14 -10 -17 -14 15 -14 1 13 0 +8 14 -10 -17 14 15 -14 1 14 0 +9 -14 -10 -17 14 -10 -14 1 15 0 +10 -14 15 -17 14 15 -14 1 16 0 +11 -14 -10 -17 14 15 -17 1 17 0 +12 -14 -10 -14 14 15 -14 1 18 0 +1 -14 -10 -17 14 15 -14 1 6 0 +$EndEntities +$Nodes +1 46 1 46 +3 1 0 46 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +-14 0 -14 +-14 -10 -14 +0 -10 -14 +0 0 -14 +-14 15 -14 +14 15 -14 +14 0 -14 +14 -10 -14 +-14 -10 -17 +-14 15 -17 +14 15 -17 +14 -10 -17 +-14 -5 -14 +-6.99999999999998 -5.00000000000001 -14 +-7 -10 -14 +-7 0 -14 +0 -5 -14 +-14 7.5 -14 +-7 7.5 -14 +0 15 -14 +14 7.5 -14 +14 -5 -14 +7 -10 -14 +-14 -10 -15.5 +-14 15 -15.5 +-14 2.5 -17 +14 15 -15.5 +0 15 -17 +14 2.5 -17 +14 -10 -15.5 +0 -10 -17 +7 -5 -14 +7 7.5 -14 +7 0 -14 +-14 -5 -15.5 +-14 7.5 -15.5 +0 15 -15.5 +14 7.5 -15.5 +14 -5 -15.5 +-7 -10 -15.5 +7 -10 -15.5 +0 2.5 -17 +7 7.5 -15.5 +-7 7.5 -15.5 +-7 -5 -15.5 +7 -5 -15.5 +$EndNodes +$Elements +18 53 1 53 +0 1 15 1 +1 1 +0 2 15 1 +2 2 +0 3 15 1 +3 3 +1 1 8 1 +4 1 3 14 +1 2 8 1 +5 5 4 19 +3 1 11 13 +6 11 5 4 6 37 19 43 27 33 20 +7 11 5 10 4 37 25 28 43 44 19 +8 9 1 2 3 35 13 24 40 15 14 +9 6 7 4 11 21 34 33 27 43 38 +10 3 9 1 4 40 35 14 17 16 45 +11 10 5 1 4 25 18 36 44 16 19 +12 7 8 4 12 22 32 34 39 46 30 +13 3 4 8 12 17 32 23 41 30 46 +14 9 10 4 12 26 44 45 31 46 42 +15 11 4 10 12 43 44 28 29 42 46 +16 9 10 1 4 26 36 35 45 16 44 +17 11 7 4 12 38 34 43 29 46 39 +18 4 3 9 12 17 40 45 46 31 41 +2 1 9 2 +19 1 2 3 13 15 14 +20 1 3 4 14 17 16 +2 2 9 3 +21 3 2 9 15 24 40 +22 3 12 8 41 30 23 +23 3 9 12 40 31 41 +2 3 9 3 +24 1 9 2 35 24 13 +25 1 5 10 18 25 36 +26 1 10 9 36 26 35 +2 4 9 3 +27 11 6 7 27 21 38 +28 12 7 8 39 22 30 +29 12 11 7 29 38 39 +2 5 9 2 +30 11 5 6 37 20 27 +31 10 5 11 25 37 28 +2 6 9 2 +32 12 9 10 31 26 42 +33 11 12 10 29 42 28 +2 7 9 3 +34 1 9 2 35 24 13 +35 5 10 1 25 36 18 +36 10 9 1 26 35 36 +2 8 9 3 +37 6 7 11 21 38 27 +38 7 8 12 22 30 39 +39 11 7 12 38 39 29 +2 9 9 3 +40 9 3 2 40 15 24 +41 3 12 8 41 30 23 +42 12 3 9 41 40 31 +2 10 9 2 +43 11 5 6 37 20 27 +44 5 11 10 37 28 25 +2 11 9 2 +45 9 10 12 26 42 31 +46 11 12 10 29 42 28 +2 12 9 7 +47 6 5 4 20 19 33 +48 3 1 2 14 13 15 +49 7 6 4 21 33 34 +50 3 4 1 17 16 14 +51 4 5 1 19 18 16 +52 8 7 4 22 34 32 +53 4 3 8 17 23 32 +$EndElements From 95d841f06dd036279d8a5158b43d79361cf0b65a Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Thu, 11 Jul 2024 15:25:48 -0500 Subject: [PATCH 04/11] Re-bootstrap --- tests/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Makefile.in b/tests/Makefile.in index 438f79930e5..b3dd2a8e046 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -2235,6 +2235,7 @@ data = matrices/geom_1_extraction_op.m \ meshes/1_quad.bxt.gz \ meshes/25_quad.bxt.gz \ meshes/bad_64bit_elem_integers.e \ + meshes/block.msh \ meshes/BlockWithHole_Patch9.bxt.gz \ meshes/constrain10to4.m \ meshes/Cube_With_Sidesets.e \ From e9ab243083528410ef0d07a100f661bd2da74e35 Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Fri, 12 Jul 2024 11:56:55 -0500 Subject: [PATCH 05/11] Add BoundingBox::max_size() --- include/geom/bounding_box.h | 9 +++++++++ src/geom/bounding_box.C | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/geom/bounding_box.h b/include/geom/bounding_box.h index 81af4c9cd38..38b63c70170 100644 --- a/include/geom/bounding_box.h +++ b/include/geom/bounding_box.h @@ -152,6 +152,15 @@ class BoundingBox : public std::pair */ void scale(const Real factor); + /** + * Returns the maximum size of a finite box extent. + * + * If the bounding box is infinite (or effectively so, e.g. using + * numeric_limits::max()) in some dimension, then that + * dimension is ignored. + */ + Real max_size() const; + /** * Formatted print, by default to \p libMesh::out. */ diff --git a/src/geom/bounding_box.C b/src/geom/bounding_box.C index c1978f9c4c4..73d0ca0ef7f 100644 --- a/src/geom/bounding_box.C +++ b/src/geom/bounding_box.C @@ -62,6 +62,21 @@ bool BoundingBox::contains_point (const Point & p) const } + +Real BoundingBox::max_size() const +{ + Real size = 0; + for (unsigned int d = 0; d != LIBMESH_DIM; ++d) + { + Real sized = this->second(d) - this->first(d); + if (!libmesh_isinf(sized)) + size = std::max(size, sized); + } + return size; +} + + + void BoundingBox::intersect_with (const BoundingBox & other_box) { this->first(0) = std::max(this->first(0), other_box.first(0)); From 8babc57d2c4b366d820bce0348de55bc8564b46a Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Fri, 12 Jul 2024 11:57:23 -0500 Subject: [PATCH 06/11] Add BoundingBox::contains_point() with tolerances --- include/geom/bounding_box.h | 11 ++++++++++ src/geom/bounding_box.C | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/geom/bounding_box.h b/include/geom/bounding_box.h index 38b63c70170..2feb728f85b 100644 --- a/include/geom/bounding_box.h +++ b/include/geom/bounding_box.h @@ -116,6 +116,17 @@ class BoundingBox : public std::pair */ bool contains_point (const Point &) const; + /** + * \returns \p true if the bounding box contains the given point, + * to within at least one of the given tolerance(s). At least one + * tolerance should be set to greater than zero; otherwise use the + * other \p contains_point overload for efficiency. + * + * Relative tolerances are computed relative to the maximum finite + * extent of the bounding box, \p max_size() + */ + bool contains_point (const Point &, Real abs_tol, Real rel_tol) const; + /** * Sets this bounding box to be the intersection with the other * bounding box. diff --git a/src/geom/bounding_box.C b/src/geom/bounding_box.C index 73d0ca0ef7f..7e87483d3db 100644 --- a/src/geom/bounding_box.C +++ b/src/geom/bounding_box.C @@ -77,6 +77,47 @@ Real BoundingBox::max_size() const +bool BoundingBox::contains_point + (const Point & p, Real abs_tol, Real rel_tol) const +{ + libmesh_assert_greater_equal(abs_tol, 0); + libmesh_assert_greater_equal(rel_tol, 0); + + // Just use the other contains_point overload + libmesh_assert_greater(rel_tol+abs_tol, 0); + + // Find absolute tolerance from relative tolerance + const Real tol = std::max(abs_tol, this->max_size()*rel_tol); + + // Make local variables first to make things more clear in a moment + const Real my_min_x = this->first(0) - tol; + const Real my_max_x = this->second(0) + tol; + bool x_int = is_between(my_min_x, p(0), my_max_x); + + bool intersection_true = x_int; + +#if LIBMESH_DIM > 1 + const Real my_min_y = this->first(1) - tol; + const Real my_max_y = this->second(1) + tol; + bool y_int = is_between(my_min_y, p(1), my_max_y); + + intersection_true = intersection_true && y_int; +#endif + + +#if LIBMESH_DIM > 2 + const Real my_min_z = this->first(2) - tol; + const Real my_max_z = this->second(2) + tol; + bool z_int = is_between(my_min_z, p(2), my_max_z); + + intersection_true = intersection_true && z_int; +#endif + + return intersection_true; +} + + + void BoundingBox::intersect_with (const BoundingBox & other_box) { this->first(0) = std::max(this->first(0), other_box.first(0)); From 3e3a033e8e256f8a33cfc54119ee47a9c7f337c0 Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Fri, 12 Jul 2024 11:57:44 -0500 Subject: [PATCH 07/11] Use tolerances in Gmsh bounding box tests If the $Entities list says the box bottoms out at 0 but we see 1e-17, that's okay. --- src/mesh/gmsh_io.C | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/mesh/gmsh_io.C b/src/mesh/gmsh_io.C index 70937756ffc..d5f38ea7561 100644 --- a/src/mesh/gmsh_io.C +++ b/src/mesh/gmsh_io.C @@ -664,9 +664,12 @@ void GmshIO::read_mesh(std::istream & in) Node * node = mesh.node_ptr(nodetrans[gmsh_node_id]); // Make sure the file is consistent about entity - // placement + // placement. Well, mostly consistent. We have + // files that claim a bounding box but still + // have points epsilon outside it. libmesh_error_msg_if - (!expected_bounding_box.contains_point(*node), + (!expected_bounding_box.contains_point + (*node, 0, /* relative */ TOLERANCE), "$Elements dim " << entity_dim << " element " << gmsh_element_id << " (entity " << entity_tag << ", " << @@ -711,7 +714,7 @@ void GmshIO::read_mesh(std::istream & in) in >> gmsh_node_id; // Make sure the file is consistent about entity - // placement + // placement. // A default bounding box is [inf,-inf] (empty); // swap that and we get [-inf,inf] (everything) @@ -726,8 +729,12 @@ void GmshIO::read_mesh(std::istream & in) Node * node = mesh.node_ptr(nodetrans[gmsh_node_id]); + // We'll accept *mostly* consistent. We have + // files that claim a bounding box but still have + // points epsilon outside it. libmesh_error_msg_if - (!expected_bounding_box.contains_point(*node), + (!expected_bounding_box.contains_point + (*node, 0, /* relative */ TOLERANCE), "$Elements dim " << entity_dim << " element " << gmsh_element_id << " (entity " << entity_tag << ") has node at " << *static_cast(node) From 52d29fd32bcf088f1d1569ad9a651844b64d8d3a Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Tue, 16 Jul 2024 08:12:14 -0500 Subject: [PATCH 08/11] Don't let casting confuse our new assertions --- src/geom/bounding_box.C | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/geom/bounding_box.C b/src/geom/bounding_box.C index 7e87483d3db..cf1c644053a 100644 --- a/src/geom/bounding_box.C +++ b/src/geom/bounding_box.C @@ -80,11 +80,11 @@ Real BoundingBox::max_size() const bool BoundingBox::contains_point (const Point & p, Real abs_tol, Real rel_tol) const { - libmesh_assert_greater_equal(abs_tol, 0); - libmesh_assert_greater_equal(rel_tol, 0); + libmesh_assert_greater_equal(abs_tol, Real(0)); + libmesh_assert_greater_equal(rel_tol, Real(0)); // Just use the other contains_point overload - libmesh_assert_greater(rel_tol+abs_tol, 0); + libmesh_assert_greater(rel_tol+abs_tol, Real(0)); // Find absolute tolerance from relative tolerance const Real tol = std::max(abs_tol, this->max_size()*rel_tol); From eaeedd306fa062d49a1ad0c6f1840151aeaba3bc Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Tue, 16 Jul 2024 12:14:53 -0500 Subject: [PATCH 09/11] Add a good .msh file (swiped from MOOSE) to tests --- tests/Makefile.am | 1 + tests/mesh/mesh_input.C | 20 ++++++- tests/meshes/circle.msh | 128 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 tests/meshes/circle.msh diff --git a/tests/Makefile.am b/tests/Makefile.am index 2a0bd0985e8..ad0aa10da3a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -155,6 +155,7 @@ data = matrices/geom_1_extraction_op.m \ meshes/bad_64bit_elem_integers.e \ meshes/block.msh \ meshes/BlockWithHole_Patch9.bxt.gz \ + meshes/circle.msh \ meshes/constrain10to4.m \ meshes/Cube_With_Sidesets.e \ meshes/exodus_elements/read_exodus_EDGE2.e \ diff --git a/tests/mesh/mesh_input.C b/tests/mesh/mesh_input.C index ea934745c0d..f65c1ee52b9 100644 --- a/tests/mesh/mesh_input.C +++ b/tests/mesh/mesh_input.C @@ -194,7 +194,8 @@ public: #endif // LIBMESH_DIM > 1 // #if LIBMESH_DIM > 1 - CPPUNIT_TEST( testGmsh ); + CPPUNIT_TEST( testBadGmsh ); + CPPUNIT_TEST( testGoodGmsh ); #endif #ifdef LIBMESH_HAVE_TETGEN @@ -1514,7 +1515,7 @@ public: helperTestingDynaQuad(mesh); } - void testGmsh () + void testBadGmsh () { LOG_UNIT_TEST; @@ -1540,6 +1541,21 @@ public: #endif } + void testGoodGmsh () + { + LOG_UNIT_TEST; + + Mesh mesh(*TestCommWorld); + + GmshIO gmsh_io(mesh); + + if (mesh.processor_id() == 0) + gmsh_io.read("meshes/circle.msh"); + MeshCommunication().broadcast(mesh); + + CPPUNIT_ASSERT_EQUAL(mesh.n_elem(), dof_id_type(14)); + } + void testTetgenIO () { #ifdef LIBMESH_HAVE_TETGEN diff --git a/tests/meshes/circle.msh b/tests/meshes/circle.msh new file mode 100644 index 00000000000..be421bac10f --- /dev/null +++ b/tests/meshes/circle.msh @@ -0,0 +1,128 @@ +$MeshFormat +4.1 0 8 +$EndMeshFormat +$PhysicalNames +2 +1 2 "outer" +2 1 "domain" +$EndPhysicalNames +$Entities +5 4 1 0 +1 1 0 0 0 +2 0 1 0 0 +3 0 0 0 0 +4 -1 0 0 0 +5 0 -1 0 0 +1 5.551115123125783e-17 0 0 1 1 0 1 2 2 1 -2 +2 -1 5.551115123125783e-17 0 0 1 0 0 2 2 -4 +3 -1 -1 0 -5.551115123125783e-17 0 0 0 2 4 -5 +4 0 -1 0 1 -5.551115123125783e-17 0 0 2 5 -1 +1 -1 -1 0 1 1 0 1 1 4 1 2 3 4 +$EndEntities +$Nodes +9 37 1 37 +0 1 0 1 +1 +1 0 0 +0 2 0 1 +2 +0 1 0 +0 4 0 1 +3 +-1 0 0 +0 5 0 1 +4 +0 -1 0 +1 1 0 3 +5 +6 +7 +0.7071067795767627 0.7071067827963323 0 +0.9238795321515167 0.3826834332336513 0 +0.3826834311765871 0.9238795330035807 0 +1 2 0 3 +8 +9 +10 +-0.7071067827963323 0.7071067795767627 0 +-0.3826834332336513 0.9238795321515167 0 +-0.9238795330035807 0.3826834311765871 0 +1 3 0 3 +11 +12 +13 +-0.7071067795767627 -0.7071067827963323 0 +-0.9238795321515167 -0.3826834332336513 0 +-0.3826834311765871 -0.9238795330035807 0 +1 4 0 3 +14 +15 +16 +0.7071067827963323 -0.7071067795767627 0 +0.3826834332336513 -0.9238795321515167 0 +0.9238795330035807 -0.3826834311765871 0 +2 1 0 21 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +0.268765817223823 0.1113264469548191 0 +-0.3632776934576478 -0.1504745480222367 0 +-0.1902402587220213 0.4476830150213186 0 +0.1820395197735081 -0.4510798723262105 0 +0.6343829086119115 0.05566322347740954 0 +0.2254026684986655 -0.1698767126856957 0 +0.591019759886754 -0.2255399361631052 0 +0.4879362984002928 0.4092166148755757 0 +0.2584332604273707 0.5773948989088254 0 +0.03926277925090085 0.2795047309880688 0 +0.4445731512849203 -0.5790933259514865 0 +-0.09512012936101064 0.7238415075106593 0 +-0.5951201293610107 0.2238415075106593 0 +-0.4486735207591768 0.5773948972990407 0 +0.09101975988675405 -0.7255399361631052 0 +-0.2625336299016273 -0.5790933275612714 0 +-0.5351922365172053 -0.4287906654092845 0 +-0.09061908684206985 -0.3007772101742236 0 +-0.6816388467288239 -0.07523727401111835 0 +-0.2767589760898345 0.148604233499541 0 +-0.04725593811691242 -0.01957405053370881 0 +$EndNodes +$Elements +2 16 1 16 +1 1 8 2 +1 1 5 6 +2 5 2 7 +2 1 9 14 +3 1 17 20 21 22 23 +4 17 5 19 24 25 26 +5 14 1 20 16 23 27 +6 5 2 19 7 28 25 +7 8 3 19 10 29 30 +8 11 4 20 13 31 32 +9 18 11 20 33 32 34 +10 3 18 19 35 36 29 +11 1 5 17 6 24 21 +12 3 11 18 12 33 35 +13 2 8 19 9 30 28 +14 4 14 20 15 27 31 +15 17 18 20 37 34 22 +16 18 17 19 37 26 36 +$EndElements From 8a0cc8e54b6054eed9b4bcc43b3c3df7d6229369 Mon Sep 17 00:00:00 2001 From: roystgnr Date: Fri, 19 Jul 2024 15:48:11 -0500 Subject: [PATCH 10/11] Apply suggestions from code review Co-authored-by: Alex Lindsay --- include/geom/bounding_box.h | 2 +- src/geom/bounding_box.C | 6 +++--- src/mesh/gmsh_io.C | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/geom/bounding_box.h b/include/geom/bounding_box.h index 2feb728f85b..138c3bd83ad 100644 --- a/include/geom/bounding_box.h +++ b/include/geom/bounding_box.h @@ -125,7 +125,7 @@ class BoundingBox : public std::pair * Relative tolerances are computed relative to the maximum finite * extent of the bounding box, \p max_size() */ - bool contains_point (const Point &, Real abs_tol, Real rel_tol) const; + bool contains_point (const Point & p, Real abs_tol, Real rel_tol) const; /** * Sets this bounding box to be the intersection with the other diff --git a/src/geom/bounding_box.C b/src/geom/bounding_box.C index cf1c644053a..12acb150467 100644 --- a/src/geom/bounding_box.C +++ b/src/geom/bounding_box.C @@ -92,14 +92,14 @@ bool BoundingBox::contains_point // Make local variables first to make things more clear in a moment const Real my_min_x = this->first(0) - tol; const Real my_max_x = this->second(0) + tol; - bool x_int = is_between(my_min_x, p(0), my_max_x); + const bool x_int = is_between(my_min_x, p(0), my_max_x); bool intersection_true = x_int; #if LIBMESH_DIM > 1 const Real my_min_y = this->first(1) - tol; const Real my_max_y = this->second(1) + tol; - bool y_int = is_between(my_min_y, p(1), my_max_y); + const bool y_int = is_between(my_min_y, p(1), my_max_y); intersection_true = intersection_true && y_int; #endif @@ -108,7 +108,7 @@ bool BoundingBox::contains_point #if LIBMESH_DIM > 2 const Real my_min_z = this->first(2) - tol; const Real my_max_z = this->second(2) + tol; - bool z_int = is_between(my_min_z, p(2), my_max_z); + const bool z_int = is_between(my_min_z, p(2), my_max_z); intersection_true = intersection_true && z_int; #endif diff --git a/src/mesh/gmsh_io.C b/src/mesh/gmsh_io.C index d5f38ea7561..e294f9b1d57 100644 --- a/src/mesh/gmsh_io.C +++ b/src/mesh/gmsh_io.C @@ -669,7 +669,7 @@ void GmshIO::read_mesh(std::istream & in) // have points epsilon outside it. libmesh_error_msg_if (!expected_bounding_box.contains_point - (*node, 0, /* relative */ TOLERANCE), + (*node, /* abs */ 0, /* relative */ TOLERANCE), "$Elements dim " << entity_dim << " element " << gmsh_element_id << " (entity " << entity_tag << ", " << @@ -734,7 +734,7 @@ void GmshIO::read_mesh(std::istream & in) // points epsilon outside it. libmesh_error_msg_if (!expected_bounding_box.contains_point - (*node, 0, /* relative */ TOLERANCE), + (*node, /* abs */ 0, /* relative */ TOLERANCE), "$Elements dim " << entity_dim << " element " << gmsh_element_id << " (entity " << entity_tag << ") has node at " << *static_cast(node) From cb9cbf5b80784f1cdb09c4e57807c686ea59c507 Mon Sep 17 00:00:00 2001 From: Roy Stogner Date: Fri, 19 Jul 2024 16:18:48 -0500 Subject: [PATCH 11/11] Handle "basically" infinite bounding box extents --- src/geom/bounding_box.C | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/geom/bounding_box.C b/src/geom/bounding_box.C index 12acb150467..f23aa22c035 100644 --- a/src/geom/bounding_box.C +++ b/src/geom/bounding_box.C @@ -69,7 +69,9 @@ Real BoundingBox::max_size() const for (unsigned int d = 0; d != LIBMESH_DIM; ++d) { Real sized = this->second(d) - this->first(d); - if (!libmesh_isinf(sized)) + if (!libmesh_isinf(sized) && + this->second(d) != std::numeric_limits::max() && + this->first(d) != -std::numeric_limits::max()) size = std::max(size, sized); } return size;