-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18914 from socratesgorilla/refineSideset2
Adding a RefineSidesetGenerator for refining boundaries
- Loading branch information
Showing
10 changed files
with
344 additions
and
0 deletions.
There are no files selected for viewing
15 changes: 15 additions & 0 deletions
15
framework/doc/content/source/meshgenerators/RefineSidesetGenerator.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# RefineSidesetGenerator | ||
|
||
!syntax description /Mesh/RefineSidesetGenerator | ||
|
||
## Overview | ||
|
||
This MeshGenerator object allows the user to refine one or more boundaries in a mesh, as well as neighboring elements of the boundary/boundaries. | ||
|
||
The user has to provide the name(s) of the boundary/boundaries to be modified, as well as the corresponding levels of refinement for each boundary. These must match up to the order of the aforementioned boundary name list, e.g. if the boundaries you wish to modify are 'left right', with 1 refinement for left, 2 for right, then the refinement list will need to look like '1 2'. By default, refinement in libmesh refines neighboring boundaries to avoid meshing problems. This generator shares this default, but it can be disabled with setting [!param](/Mesh/RefineSidesetGenerator/enable_neighbor_refinement) to `false`. Additionally, the user must provide the type of refinement to perform in [!param](/Mesh/RefineSidesetGenerator/boundary_side) where "primary" merely refines the elements on the boundary, "secondary" only refines the neighbors of the boundary, and "both" refines both the elements on the boundary and its neighboring elements. | ||
|
||
!syntax parameters /Mesh/RefineSidesetGenerator | ||
|
||
!syntax inputs /Mesh/RefineSidesetGenerator | ||
|
||
!syntax children /Mesh/RefineSidesetGenerator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
//* This file is part of the MOOSE framework | ||
//* https://www.mooseframework.org | ||
//* | ||
//* All rights reserved, see COPYRIGHT for full restrictions | ||
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT | ||
//* | ||
//* Licensed under LGPL 2.1, please see LICENSE for details | ||
//* https://www.gnu.org/licenses/lgpl-2.1.html | ||
|
||
#pragma once | ||
|
||
#include "MeshGenerator.h" | ||
|
||
/** | ||
* MeshGenerator for refining one or more sidesets | ||
*/ | ||
class RefineSidesetGenerator : public MeshGenerator | ||
{ | ||
public: | ||
static InputParameters validParams(); | ||
|
||
RefineSidesetGenerator(const InputParameters & parameters); | ||
|
||
protected: | ||
virtual std::unique_ptr<MeshBase> generate() override; | ||
|
||
private: | ||
/// Input mesh to refine | ||
std::unique_ptr<MeshBase> & _input; | ||
|
||
/// List of boundarie(s) to refine | ||
const std::vector<BoundaryName> _boundaries; | ||
|
||
/// The amount of times to refine each boundary, corresponding to their index in 'boundaries' | ||
const std::vector<int> _refinement; | ||
|
||
/// Toggles whether neighboring level one elements should be refined or not. Defaults to true. | ||
const bool _enable_neighbor_refinement; | ||
|
||
/// Side(s) of the boundary/boundaries to be refined. Can be either "primary"(just the boundary elements), "secondary"(just the neighboring elements), or "both." | ||
const MultiMooseEnum _boundary_side; | ||
|
||
/** | ||
* The actual function refining the boundaries. This is done recursively in order | ||
* to minimize the number of refinement iterations to as little as possible. | ||
* @param boundary_ids Vector of boundary_ids to refine | ||
* @param mesh The mesh to refine | ||
* @param refinement Vector describing how many times to refine each boundary, | ||
* corresponding to their placement in boundary_ids | ||
* @param max Max value of all the refinement levels in the above vector | ||
* @param ref_step Step counter for the recursive function, defaults to 0 for initial call. | ||
* @return Unique pointer to a refined MeshBase | ||
*/ | ||
std::unique_ptr<MeshBase> recursive_refine(const std::vector<boundary_id_type> boundary_ids, | ||
std::unique_ptr<MeshBase> & mesh, | ||
const std::vector<int> refinement, | ||
const int max, | ||
int ref_step = 0); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
//* This file is part of the MOOSE framework | ||
//* https://www.mooseframework.org | ||
//* | ||
//* All rights reserved, see COPYRIGHT for full restrictions | ||
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT | ||
//* | ||
//* Licensed under LGPL 2.1, please see LICENSE for details | ||
//* https://www.gnu.org/licenses/lgpl-2.1.html | ||
|
||
#include "RefineSidesetGenerator.h" | ||
#include "MooseMeshUtils.h" | ||
|
||
#include "libmesh/elem.h" | ||
#include "libmesh/mesh_refinement.h" | ||
#include "CastUniquePointer.h" | ||
|
||
registerMooseObject("MooseApp", RefineSidesetGenerator); | ||
|
||
InputParameters | ||
RefineSidesetGenerator::validParams() | ||
{ | ||
InputParameters params = MeshGenerator::validParams(); | ||
params.addClassDescription("Mesh generator which refines one or more sidesets"); | ||
params.addRequiredParam<MeshGeneratorName>("input", "Input mesh to modify"); | ||
params.addRequiredParam<std::vector<BoundaryName>>("boundaries", | ||
"The list of boundaries to be modified"); | ||
params.addRequiredParam<std::vector<int>>( | ||
"refinement", | ||
"The amount of times to refine each sideset, corresponding to their index in 'boundaries'"); | ||
params.addParam<bool>( | ||
"enable_neighbor_refinement", | ||
true, | ||
"Toggles whether neighboring level one elements should be refined or not. Defaults to true"); | ||
MultiMooseEnum boundary_side("primary secondary both", "both"); | ||
params.addParam<MultiMooseEnum>("boundary_side", | ||
boundary_side, | ||
"Whether the generator should refine itself(primary), its " | ||
"neighbors(secondary), or itself and its neighbors(both)"); | ||
|
||
return params; | ||
} | ||
|
||
RefineSidesetGenerator::RefineSidesetGenerator(const InputParameters & parameters) | ||
: MeshGenerator(parameters), | ||
_input(getMesh("input")), | ||
_boundaries(getParam<std::vector<BoundaryName>>("boundaries")), | ||
_refinement(getParam<std::vector<int>>("refinement")), | ||
_enable_neighbor_refinement(getParam<bool>("enable_neighbor_refinement")), | ||
_boundary_side(getParam<MultiMooseEnum>("boundary_side")) | ||
{ | ||
} | ||
|
||
std::unique_ptr<MeshBase> | ||
RefineSidesetGenerator::generate() | ||
{ | ||
// Get the list of boundary ids from the boundary names | ||
const auto boundary_ids = MooseMeshUtils::getBoundaryIDs( | ||
*_input, getParam<std::vector<BoundaryName>>("boundaries"), false); | ||
|
||
// Check that the boundary ids/names exist in the mesh | ||
for (std::size_t i = 0; i < boundary_ids.size(); ++i) | ||
if (boundary_ids[i] == Moose::INVALID_BOUNDARY_ID) | ||
paramError("boundaries", | ||
"The boundary '", | ||
getParam<std::vector<BoundaryName>>("boundaries")[i], | ||
"' was not found within the mesh"); | ||
std::unique_ptr<MeshBase> mesh = std::move(_input); | ||
int max = *std::max_element(_refinement.begin(), _refinement.end()); | ||
return recursive_refine(boundary_ids, mesh, _refinement, max); | ||
} | ||
|
||
std::unique_ptr<MeshBase> | ||
RefineSidesetGenerator::recursive_refine(std::vector<boundary_id_type> boundary_ids, | ||
std::unique_ptr<MeshBase> & mesh, | ||
std::vector<int> refinement, | ||
int max, | ||
int ref_step) | ||
{ | ||
// If the refinement step has reached the largest value in the _refinement array, return the mesh, | ||
// as we are done. | ||
if (ref_step == max) | ||
return dynamic_pointer_cast<MeshBase>(mesh); | ||
mesh->prepare_for_use(); | ||
std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>> sideList = | ||
mesh->get_boundary_info().build_active_side_list(); | ||
for (std::size_t i = 0; i < boundary_ids.size(); i++) | ||
{ | ||
if (refinement[i] > 0 && refinement[i] > ref_step) | ||
{ | ||
for (std::tuple<dof_id_type, unsigned short int, boundary_id_type> tuple : sideList) | ||
{ | ||
if (std::get<2>(tuple) == boundary_ids[i]) | ||
{ | ||
Elem * elem = mesh->elem_ptr(std::get<0>(tuple)); | ||
if (_boundary_side[i] == "primary" || _boundary_side[i] == "both") | ||
elem->set_refinement_flag(Elem::REFINE); | ||
if (_boundary_side[i] == "secondary" || _boundary_side[i] == "both") | ||
{ | ||
auto neighbor = elem->neighbor_ptr(std::get<1>(tuple)); | ||
// when we have multiple domains, domains will only refine the elements that they own | ||
// since there can be instances where there is no neighbor, this null_ptr check is | ||
// necessary | ||
if (neighbor) | ||
{ | ||
if (neighbor->active()) | ||
neighbor->set_refinement_flag(Elem::REFINE); | ||
else | ||
{ | ||
std::vector<Elem *> family_tree; | ||
neighbor->active_family_tree_by_neighbor(family_tree, elem); | ||
for (auto child_elem : family_tree) | ||
child_elem->set_refinement_flag(Elem::REFINE); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
MeshRefinement refinedmesh(*mesh); | ||
if (!_enable_neighbor_refinement) | ||
refinedmesh.face_level_mismatch_limit() = 0; | ||
refinedmesh.refine_elements(); | ||
ref_step++; | ||
return recursive_refine(boundary_ids, mesh, refinement, max, ref_step); | ||
} |
Binary file added
BIN
+257 KB
test/tests/meshgenerators/refine_sideset_generator/gold/test_left_in.e
Binary file not shown.
Binary file added
BIN
+154 KB
test/tests/meshgenerators/refine_sideset_generator/gold/test_multi_in.e
Binary file not shown.
Binary file added
BIN
+79.8 KB
test/tests/meshgenerators/refine_sideset_generator/gold/test_secondary_in.e
Binary file not shown.
30 changes: 30 additions & 0 deletions
30
test/tests/meshgenerators/refine_sideset_generator/test_left.i
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
[Mesh] | ||
[eg] | ||
type = CartesianMeshGenerator | ||
dim = 3 | ||
dx = '2 1 1' | ||
dy = '2 3' | ||
dz = '0.4 0.5 0.6 0.7' | ||
ix = '2 1 1' | ||
iy = '2 3' | ||
iz = '1 1 1 1' | ||
subdomain_id = '0 1 1 1 | ||
1 2 0 1 | ||
0 1 1 1 | ||
2 2 2 2 | ||
3 3 1 3 | ||
1 1 1 1' | ||
[] | ||
[refine] | ||
type = RefineSidesetGenerator | ||
input = eg | ||
boundaries = 'left' | ||
refinement = '3' | ||
boundary_side = 'primary' | ||
enable_neighbor_refinement = false | ||
[] | ||
[] | ||
|
||
[Outputs] | ||
exodus = true | ||
[] |
37 changes: 37 additions & 0 deletions
37
test/tests/meshgenerators/refine_sideset_generator/test_multi.i
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
[Mesh] | ||
[eg] | ||
type = CartesianMeshGenerator | ||
dim = 3 | ||
dx = '2 1 1' | ||
dy = '2 3' | ||
dz = '0.4 0.5 0.6 0.7' | ||
ix = '2 1 1' | ||
iy = '2 3' | ||
iz = '1 1 1 1' | ||
subdomain_id = '0 1 1 1 | ||
1 2 0 1 | ||
0 1 1 1 | ||
2 2 2 2 | ||
3 3 1 3 | ||
1 1 1 1' | ||
[] | ||
[sideset] | ||
type = SideSetsBetweenSubdomainsGenerator | ||
input = eg | ||
primary_block = 1 | ||
paired_block = 2 | ||
new_boundary = sideset_1 | ||
[] | ||
[refine] | ||
type = RefineSidesetGenerator | ||
input = sideset | ||
boundaries = 'sideset_1' | ||
refinement = '2' | ||
boundary_side = 'both' | ||
enable_neighbor_refinement = false | ||
[] | ||
[] | ||
|
||
[Outputs] | ||
exodus = true | ||
[] |
37 changes: 37 additions & 0 deletions
37
test/tests/meshgenerators/refine_sideset_generator/test_secondary.i
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
[Mesh] | ||
[eg] | ||
type = CartesianMeshGenerator | ||
dim = 3 | ||
dx = '2 1 1' | ||
dy = '2 3' | ||
dz = '0.4 0.5 0.6 0.7' | ||
ix = '2 1 1' | ||
iy = '2 3' | ||
iz = '1 1 1 1' | ||
subdomain_id = '0 1 1 1 | ||
1 2 0 1 | ||
0 1 1 1 | ||
2 2 2 2 | ||
3 3 1 3 | ||
1 1 1 1' | ||
[] | ||
[sideset] | ||
type = SideSetsBetweenSubdomainsGenerator | ||
input = eg | ||
primary_block = 1 | ||
paired_block = 2 | ||
new_boundary = sideset_1 | ||
[] | ||
[refine] | ||
type = RefineSidesetGenerator | ||
input = sideset | ||
boundaries = 'sideset_1' | ||
refinement = '2' | ||
boundary_side = 'secondary' | ||
enable_neighbor_refinement = false | ||
[] | ||
[] | ||
|
||
[Outputs] | ||
exodus = true | ||
[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
[Tests] | ||
issues = '#18913' | ||
design = 'meshgenerators/RefineSidesetGenerator.md' | ||
[generate] | ||
requirement = 'The system shall support the ability to refine' | ||
|
||
[left] | ||
type = 'Exodiff' | ||
input = 'test_left.i' | ||
exodiff = 'test_left_in.e' | ||
cli_args = '--mesh-only' | ||
recover = false | ||
detail = 'neighboring elements of an external boundary along a mesh' | ||
[] | ||
[secondary] | ||
type = 'Exodiff' | ||
input = 'test_secondary.i' | ||
exodiff = 'test_secondary_in.e' | ||
cli_args = '--mesh-only' | ||
recover = false | ||
detail = 'neighboring elements of a specified boundary along a mesh' | ||
[] | ||
[both] | ||
type = 'Exodiff' | ||
input = 'test_multi.i' | ||
exodiff = 'test_multi_in.e' | ||
recover = false | ||
cli_args = "--mesh-only" | ||
detail = 'both the neighboring elements of, and the elements along, a specified boundary' | ||
[] | ||
[] | ||
[failureBoundary] | ||
type = 'RunException' | ||
input = 'test_multi.i' | ||
recover = false | ||
cli_args = "Mesh/refine/boundaries='foo' --mesh-only" | ||
expect_err = "The boundary *" | ||
requirement = 'The system shall error if the specified boundary to be refined does not exist' | ||
[] | ||
[] |