11use crate :: connectivity:: { Tet4Connectivity , Tri3d2Connectivity , Tri3d3Connectivity } ;
22use crate :: mesh:: Mesh ;
33use eyre:: { eyre, Context } ;
4- use log:: warn;
54use nalgebra:: allocator:: Allocator ;
65use nalgebra:: { DefaultAllocator , DimName , OPoint , RealField } ;
6+ use num:: ToPrimitive ;
77use std:: path:: Path ;
88
99/// Loads a [`Mesh`] from a Gmsh MSH file at the given path.
6161 vertices. extend ( block_vertices) ;
6262 }
6363
64+ if vertices. len ( )
65+ != msh_nodes
66+ . num_nodes
67+ . to_usize ( )
68+ . expect ( "failed to convert num_nodes to usize" )
69+ {
70+ return Err ( eyre ! (
71+ "only {} vertices were read but msh file claims to contain {} nodes" ,
72+ vertices. len( ) ,
73+ msh_nodes. num_nodes
74+ ) ) ;
75+ }
76+
6477 // Collect all connectivity matching the target connectivity
6578 for element_block in & msh_elements. element_blocks {
6679 let block_connectivity = connectivity_from_element_block ( element_block) ?;
@@ -81,20 +94,29 @@ where
8194{
8295 // Ensure that node tags are consecutive
8396 if node_block. node_tags . is_some ( ) {
84- return Err ( eyre ! ( "node block tags are not consecutive in msh file" ) ) ;
97+ return Err ( eyre ! (
98+ "node block tags are not consecutive in msh file (sparse tags are not supported)"
99+ ) ) ;
85100 }
86101
87- // Check dimension of node block vertices
102+ // Note: The MSH `node_block`'s `entity_dim` does not seem to correspond to the geometrical
103+ // dimension of the points. Rather it seems to correspond to the dimension of the "physical"
104+ // object represented by the node block.
105+ // When creating primitives in Gmsh for example, the nodes of a triangulation of a sphere are
106+ // divided into node_blocks representing its equator, surface and volume and all of them are
107+ // referenced by the volumetric elements.
108+ // In addition, all node blocks have to be read in order for the global `node_tag` indexing to
109+ // be consistent work.
110+ /*
88111 if node_block
89112 .entity_dim
90113 .to_usize()
91114 .ok_or_else(|| eyre!("error converting node block entity dimension to usize"))?
92115 != D::dim()
93116 {
94- // TODO: When can this happen?
95- warn ! ( "Node block entity does not have the right dimension for this mesh. Will be read as if they were of the same dimension." ) ;
96- //return Err(eyre!("node block entity does not have the right dimension for this mesh"));
117+ return Err(eyre!("node block entity does not have the right dimension for this mesh"));
97118 }
119+ */
98120
99121 let mut vertices = Vec :: with_capacity ( node_block. nodes . len ( ) ) ;
100122
@@ -114,7 +136,9 @@ where
114136{
115137 // Ensure that element tags are consecutive
116138 if element_block. element_tags . is_some ( ) {
117- return Err ( eyre ! ( "element block tags are not consecutive in msh file" ) ) ;
139+ return Err ( eyre ! (
140+ "element block tags are not consecutive in msh file (sparse tags are not supported)"
141+ ) ) ;
118142 }
119143
120144 if !element_block_matches_connectivity :: < C , _ > ( element_block) {
@@ -229,7 +253,7 @@ impl_msh_connectivity!(Tet4Connectivity, Tet4, num_nodes = 4);
229253
230254#[ cfg( test) ]
231255mod msh_tests {
232- use crate :: connectivity:: { Tet4Connectivity , Tri3d2Connectivity } ;
256+ use crate :: connectivity:: { Tet4Connectivity , Tri3d2Connectivity , Tri3d3Connectivity } ;
233257 use crate :: io:: msh:: load_msh_from_file;
234258 use nalgebra:: { U2 , U3 } ;
235259
@@ -250,4 +274,14 @@ mod msh_tests {
250274 assert_eq ! ( mesh. connectivity( ) . len( ) , 110 ) ;
251275 Ok ( ( ) )
252276 }
277+
278+ #[ test]
279+ fn load_msh_rect_tri3d3 ( ) -> eyre:: Result < ( ) > {
280+ // Loading a 2D triangle mesh to a 3D triangle mesh should work
281+ let mesh = load_msh_from_file :: < f64 , U3 , Tri3d3Connectivity , _ > ( "assets/meshes/rectangle_110.msh" ) ?;
282+
283+ assert_eq ! ( mesh. vertices( ) . len( ) , 70 ) ;
284+ assert_eq ! ( mesh. connectivity( ) . len( ) , 110 ) ;
285+ Ok ( ( ) )
286+ }
253287}
0 commit comments