-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added diagnostic check for watertight nodesets #29068
base: next
Are you sure you want to change the base?
Changes from all commits
b26277b
ab61eb3
d7a8ed0
2006878
6004474
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,10 @@ MeshDiagnosticsGenerator::validParams() | |
"check_for_watertight_sidesets", | ||
chk_option, | ||
"whether to check for external sides that are not assigned to any sidesets"); | ||
params.addParam<MooseEnum>( | ||
"check_for_watertight_nodesets", | ||
chk_option, | ||
"whether to check for external nodes that are not assigned to any nodeset"); | ||
params.addParam<MooseEnum>( | ||
"examine_element_volumes", chk_option, "whether to examine volume of the elements"); | ||
params.addParam<Real>("minimum_element_volumes", 1e-16, "minimum size for element volume"); | ||
|
@@ -80,6 +84,7 @@ MeshDiagnosticsGenerator::MeshDiagnosticsGenerator(const InputParameters & param | |
_input(getMesh("input")), | ||
_check_sidesets_orientation(getParam<MooseEnum>("examine_sidesets_orientation")), | ||
_check_watertight_sidesets(getParam<MooseEnum>("check_for_watertight_sidesets")), | ||
_check_watertight_nodesets(getParam<MooseEnum>("check_for_watertight_nodesets")), | ||
_check_element_volumes(getParam<MooseEnum>("examine_element_volumes")), | ||
_min_volume(getParam<Real>("minimum_element_volumes")), | ||
_max_volume(getParam<Real>("maximum_element_volumes")), | ||
|
@@ -103,10 +108,10 @@ MeshDiagnosticsGenerator::MeshDiagnosticsGenerator(const InputParameters & param | |
paramError("examine_non_conformality", | ||
"You must set this parameter to true to trigger mesh conformality check"); | ||
if (_check_sidesets_orientation == "NO_CHECK" && _check_watertight_sidesets == "NO_CHECK" && | ||
_check_element_volumes == "NO_CHECK" && _check_element_types == "NO_CHECK" && | ||
_check_element_overlap == "NO_CHECK" && _check_non_planar_sides == "NO_CHECK" && | ||
_check_non_conformal_mesh == "NO_CHECK" && _check_adaptivity_non_conformality == "NO_CHECK" && | ||
_check_local_jacobian == "NO_CHECK") | ||
_check_watertight_nodesets == "NO_CHECK" && _check_element_volumes == "NO_CHECK" && | ||
_check_element_types == "NO_CHECK" && _check_element_overlap == "NO_CHECK" && | ||
_check_non_planar_sides == "NO_CHECK" && _check_non_conformal_mesh == "NO_CHECK" && | ||
_check_adaptivity_non_conformality == "NO_CHECK" && _check_local_jacobian == "NO_CHECK") | ||
mooseError("You need to turn on at least one diagnostic. Did you misspell a parameter?"); | ||
} | ||
|
||
|
@@ -129,6 +134,9 @@ MeshDiagnosticsGenerator::generate() | |
if (_check_watertight_sidesets != "NO_CHECK") | ||
checkWaterTightSidesets(mesh); | ||
|
||
if (_check_watertight_nodesets != "NO_CHECK") | ||
checkWatertightNodesets(mesh); | ||
|
||
if (_check_element_volumes != "NO_CHECK") | ||
checkElementVolumes(mesh); | ||
|
||
|
@@ -335,6 +343,66 @@ MeshDiagnosticsGenerator::checkWaterTightSidesets(const std::unique_ptr<MeshBase | |
diagnosticsLog(message, _check_watertight_sidesets, num_faces_without_sideset); | ||
} | ||
|
||
void | ||
MeshDiagnosticsGenerator::checkWatertightNodesets(const std::unique_ptr<MeshBase> & mesh) const | ||
{ | ||
/* | ||
Diagnostic Overview: | ||
1) Mesh precheck | ||
2) Loop through all elements | ||
3) Loop through all sides of that element | ||
4) If side is external loop through its nodes | ||
5) If node is not associated with any nodeset add to list | ||
6) Print out node id | ||
*/ | ||
if (mesh->mesh_dimension() < 2) | ||
mooseError("The nodeset check only works for 2D and 3D meshes"); | ||
auto & boundary_info = mesh->get_boundary_info(); | ||
boundary_info.build_side_list(); | ||
const auto nodeset_map = boundary_info.get_nodeset_map(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where is the _boundary_node_id being initialized in libmesh? is the previous call doing it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe that gets initialized when the mesh is first read in or made? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let s be sure we dont need to "prepare_for_use" for this diagnostics to work There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I looked into it. The node ids get added to _boundary_node_id after execute_mesh_generators is called in ActionWarehouse.C. From what I can tell the mesh is always initialized before this test could ever be called. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
wouldnt that be too late then? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, it's the execute_mesh_generators task that initializes _boundary_node_id. After initialization mesh diagnostics runs. So that task runs both I believe, but it should initialize first. |
||
unsigned int num_nodes_without_nodeset = 0; | ||
std::set<dof_id_type> checked_nodes_id; | ||
|
||
for (const auto elem : mesh->active_element_ptr_range()) | ||
{ | ||
for (const auto i : elem->side_index_range()) | ||
{ | ||
// Check if side is external | ||
if (elem->neighbor_ptr(i) == nullptr) | ||
{ | ||
// Side is external, now check nodes | ||
auto side = elem->side_ptr(i); | ||
const auto & node_list = side->get_nodes(); | ||
for (unsigned int j = 0; j < side->n_nodes(); j++) | ||
{ | ||
const auto node = node_list[j]; | ||
if (checked_nodes_id.count(node->id())) | ||
continue; | ||
// if node is not part of nodeset map add it to list of bad nodes | ||
if (nodeset_map.count(node) == 0) | ||
{ | ||
// This node does not have a nodeset!!! | ||
num_nodes_without_nodeset++; | ||
checked_nodes_id.insert(node->id()); | ||
std::string message; | ||
if (num_nodes_without_nodeset < _num_outputs) | ||
{ | ||
message = | ||
"Node " + std::to_string(node->id()) + | ||
" is on an external boundary of the mesh, but has not been assigned to a nodeset"; | ||
_console << message << std::endl; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
std::string message; | ||
message = "Number of external nodes that have not been assigned to a nodeset: " + | ||
std::to_string(num_nodes_without_nodeset); | ||
diagnosticsLog(message, _check_watertight_nodesets, num_nodes_without_nodeset); | ||
} | ||
|
||
void | ||
MeshDiagnosticsGenerator::checkElementVolumes(const std::unique_ptr<MeshBase> & mesh) const | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[Mesh] | ||
[gmg] | ||
type = GeneratedMeshGenerator | ||
dim = 2 | ||
nx = 2 | ||
ny = 2 | ||
[] | ||
[deletion] | ||
type = BoundaryDeletionGenerator | ||
input = gmg | ||
boundary_names = 'right' | ||
[] | ||
[diag] | ||
type = MeshDiagnosticsGenerator | ||
input = deletion | ||
check_for_watertight_nodesets = INFO | ||
[] | ||
[] | ||
|
||
[Outputs] | ||
exodus = true | ||
[] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
[Mesh] | ||
[gmg] | ||
type = GeneratedMeshGenerator | ||
dim = 3 | ||
nx = 2 | ||
ny = 2 | ||
nz = 2 | ||
[] | ||
[deletion] | ||
type = BoundaryDeletionGenerator | ||
input = gmg | ||
boundary_names = 'right' | ||
[] | ||
[diag] | ||
type = MeshDiagnosticsGenerator | ||
input = deletion | ||
check_for_watertight_nodesets = INFO | ||
[] | ||
[] | ||
|
||
[Outputs] | ||
exodus = true | ||
[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let s add a parameter for the nodesets that are supposed to englobe the entire mesh. when this parameter is in use, the nodes are only checked against those "blessed" nodesets
same for sidsets
actually now that I see that this is not an option for sidesets, let s keep it for future work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I'll open a new issue for adding that parameter to the sideset and nodeset checks.