@@ -45,6 +45,10 @@ MeshDiagnosticsGenerator::validParams()
45
45
"check_for_watertight_sidesets" ,
46
46
chk_option ,
47
47
"whether to check for external sides that are not assigned to any sidesets" );
48
+ params .addParam < MooseEnum > (
49
+ "check_for_watertight_nodesets" ,
50
+ chk_option ,
51
+ "whether to check for external nodes that are not assigned to any nodeset" );
48
52
params .addParam < MooseEnum > (
49
53
"examine_element_volumes" , chk_option , "whether to examine volume of the elements" );
50
54
params .addParam < Real > ("minimum_element_volumes" , 1e-16 , "minimum size for element volume" );
@@ -80,6 +84,7 @@ MeshDiagnosticsGenerator::MeshDiagnosticsGenerator(const InputParameters & param
80
84
_input (getMesh ("input" )),
81
85
_check_sidesets_orientation (getParam < MooseEnum > ("examine_sidesets_orientation" )),
82
86
_check_watertight_sidesets (getParam < MooseEnum > ("check_for_watertight_sidesets" )),
87
+ _check_watertight_nodesets (getParam < MooseEnum > ("check_for_watertight_nodesets" )),
83
88
_check_element_volumes (getParam < MooseEnum > ("examine_element_volumes" )),
84
89
_min_volume (getParam < Real > ("minimum_element_volumes" )),
85
90
_max_volume (getParam < Real > ("maximum_element_volumes" )),
@@ -103,10 +108,10 @@ MeshDiagnosticsGenerator::MeshDiagnosticsGenerator(const InputParameters & param
103
108
paramError ("examine_non_conformality" ,
104
109
"You must set this parameter to true to trigger mesh conformality check" );
105
110
if (_check_sidesets_orientation == "NO_CHECK" && _check_watertight_sidesets == "NO_CHECK" &&
106
- _check_element_volumes == "NO_CHECK" && _check_element_types == "NO_CHECK" &&
107
- _check_element_overlap == "NO_CHECK" && _check_non_planar_sides == "NO_CHECK" &&
108
- _check_non_conformal_mesh == "NO_CHECK" && _check_adaptivity_non_conformality == "NO_CHECK" &&
109
- _check_local_jacobian == "NO_CHECK" )
111
+ _check_watertight_nodesets == "NO_CHECK" && _check_element_volumes == "NO_CHECK" &&
112
+ _check_element_types == "NO_CHECK" && _check_element_overlap == "NO_CHECK" &&
113
+ _check_non_planar_sides == "NO_CHECK" && _check_non_conformal_mesh == "NO_CHECK" &&
114
+ _check_adaptivity_non_conformality == "NO_CHECK" && _check_local_jacobian == "NO_CHECK" )
110
115
mooseError ("You need to turn on at least one diagnostic. Did you misspell a parameter?" );
111
116
}
112
117
@@ -129,6 +134,9 @@ MeshDiagnosticsGenerator::generate()
129
134
if (_check_watertight_sidesets != "NO_CHECK" )
130
135
checkWaterTightSidesets (mesh );
131
136
137
+ if (_check_watertight_nodesets != "NO_CHECK" )
138
+ checkWatertightNodesets (mesh );
139
+
132
140
if (_check_element_volumes != "NO_CHECK" )
133
141
checkElementVolumes (mesh );
134
142
@@ -335,6 +343,64 @@ MeshDiagnosticsGenerator::checkWaterTightSidesets(const std::unique_ptr<MeshBase
335
343
diagnosticsLog (message , _check_watertight_sidesets , num_faces_without_sideset );
336
344
}
337
345
346
+ void
347
+ MeshDiagnosticsGenerator ::checkWatertightNodesets (const std ::unique_ptr < MeshBase > & mesh ) const
348
+ {
349
+ /*
350
+ Diagnostic Overview:
351
+ 1) Mesh precheck
352
+ 2) Loop through all elements
353
+ 3) Loop through all sides of that element
354
+ 4) If side is external loop through its nodes
355
+ 5) If node is not associated with any nodeset add to list
356
+ 6) Print out node id
357
+ */
358
+ if (mesh -> mesh_dimension () < 2 )
359
+ mooseError ("The nodeset check only works for 2D and 3D meshes" );
360
+ auto & boundary_info = mesh -> get_boundary_info ();
361
+ unsigned int num_nodes_without_nodeset = 0 ;
362
+ std ::set < dof_id_type > checked_nodes_id ;
363
+
364
+ for (const auto elem : mesh -> active_element_ptr_range ())
365
+ {
366
+ for (const auto i : elem -> side_index_range ())
367
+ {
368
+ // Check if side is external
369
+ if (elem -> neighbor_ptr (i ) == nullptr )
370
+ {
371
+ // Side is external, now check nodes
372
+ auto side = elem -> side_ptr (i );
373
+ const auto & node_list = side -> get_nodes ();
374
+ for (unsigned int j = 0 ; j < side -> n_nodes (); j ++ )
375
+ {
376
+ const auto node = node_list [j ];
377
+ if (checked_nodes_id .count (node -> id ()))
378
+ continue ;
379
+ // if node has no nodeset, add it to list of bad nodes
380
+ if (boundary_info .n_boundary_ids (node ) == 0 )
381
+ {
382
+ // This node does not have a nodeset!!!
383
+ num_nodes_without_nodeset ++ ;
384
+ checked_nodes_id .insert (node -> id ());
385
+ std ::string message ;
386
+ if (num_nodes_without_nodeset < _num_outputs )
387
+ {
388
+ message =
389
+ "Node " + std ::to_string (node -> id ()) +
390
+ " is on an external boundary of the mesh, but has not been assigned to a nodeset" ;
391
+ _console << message << std ::endl ;
392
+ }
393
+ }
394
+ }
395
+ }
396
+ }
397
+ }
398
+ std ::string message ;
399
+ message = "Number of external nodes that have not been assigned to a nodeset: " +
400
+ std ::to_string (num_nodes_without_nodeset );
401
+ diagnosticsLog (message , _check_watertight_nodesets , num_nodes_without_nodeset );
402
+ }
403
+
338
404
void
339
405
MeshDiagnosticsGenerator ::checkElementVolumes (const std ::unique_ptr < MeshBase > & mesh ) const
340
406
{
0 commit comments