Skip to content

Commit

Permalink
Add a SideSetExtruderGenerator and related documentation to the suppo…
Browse files Browse the repository at this point in the history
…rting sub-generators.

ref idaholab#20880
  • Loading branch information
RocksSavage authored and maxnezdyur committed Feb 12, 2023
1 parent 8fcb48f commit 72ead2f
Show file tree
Hide file tree
Showing 19 changed files with 434 additions and 0 deletions.
Expand Up @@ -8,6 +8,10 @@ The mesh extruder generator is a tool for increasing the dimensionality of a low
to one or more copies of its corresponding higher dimensional element along the specified axis. The Mesh Extruder can also add
in the extra sidesets resulting from increasing the dimensionality of the original mesh. Existing sidesets are extruded.

Through the `existing_subdomains`, `layers`, and `new_ids` options, it is possible to specify that an extruded block exists in some layers,
but not others. This allows for serrated patterns and gaps. Note that no error will be thrown if the resulting blocks overlap. These three
options must have the same number of values given to them. The extrusion vector may use decimal values.

## Visual Example

### Input 2D Mesh
Expand Down
@@ -0,0 +1,65 @@
# SideSetExtruderGenerator

!syntax description /Mesh/SideSetExtruderGenerator

## Overview

The SideSetExtruder Generator is for "pulling" mesh in a direction. Given a sideset and a direction(vector), it adds to the mesh. SideSetExtruder differs from [MeshExtruderGenerator](MeshExtruderGenerator.md) in that the extrusion stays in the same dimension as the sideset it is pulling on (MeshExtruderGenerator is for pulling 2 dimensional shapes into 3 dimensions).

SideSetExtruder will not throw any errors if you extrude a mesh through (collide with) another mesh. It will throw an error if the extrusion vector would create a mesh with a negative determinant (or rather, [MeshExtruderGenerator](MeshExtruderGenerator.md) throws the error). The extrusion vector is applied relative to the sideset given, not from the origin point of the mesh. The extrusion vector must be a 3D vector even if you are only extruding a 2D mesh; in such a case, let the z component be 0 (e.g., `extrusion_vector = '1 0.5 0'`)

The output will have no sidesets, even the sideset you extruded from will be gone. The user is expected to use the other side-set generating generators on the output if sidesets are needed.

## Visual Example

### Input 2D Mesh

!media large_media/framework/meshgenerators/sideset_extruder_before.png caption=Before: a square, with sidesets on each side.

### Output of SideSetExtruderGenerator

!media large_media/framework/meshgenerators/sideset_extruder_after.png caption=After, the right sideset has been extruded in the < 1, 0.5, 0> direction.

SideSetExtruderGenerator is actually a mere wrapper of 4 other generators: [LowerDBlockFromSidesetGenerator](LowerDBlockFromSidesetGenerator.md), [BlockToMeshConverterGenerator](BlockToMeshConverterGenerator.md), [MeshExtruderGenerator](MeshExtruderGenerator.md), and [StitchedMeshGenerator](StitchedMeshGenerator.md). SideSetExtruderGenerator's output from the example above is exactly equivalent to the output of a recipe like this:

```
[Mesh]
[square]
type = GeneratedMeshGenerator
dim = 2
[]
[lowerDblock]
type = LowerDBlockFromSidesetGenerator
input = square
new_block_name = "extrusions0"
sidesets = "right"
[]
[separateMesh]
type = BlockToMeshConverterGenerator
input = lowerDblock
target_blocks = extrusions0
[]
[extrude]
type = MeshExtruderGenerator
input = separateMesh
num_layers = 3
extrusion_vector = '1 0.5 0'
bottom_sideset = 'new_bottom'
top_sideset = 'new_top'
[]
[stitch]
type = StitchedMeshGenerator
inputs = 'square extrude'
stitch_boundaries_pairs = 'right new_bottom'
[]
[]
```

If you are needing to tweak the output of SideSetExtruderGenerator, you may be better off manually running these operations instead. SideSetExtruderGenerator uses the defaults of these sub-generators.

!syntax parameters /Mesh/SideSetExtruderGenerator

!syntax inputs /Mesh/SideSetExtruderGenerator

!syntax children /Mesh/SideSetExtruderGenerator
Expand Up @@ -15,6 +15,8 @@ Consider the following three meshes.
Using the `StitchedMeshGenerator` object from within the [Mesh](/Mesh/index.md) block of the input file, as shown in the input
file snippet below, these three square meshes are joined into a single mesh as shown in Figure 4.

Note that the way that the meshes are merged gives precedence to the left-most mesh listed in terms of sidesets: the sidesets of the second, third, etc meshes will be subsumed into the sidesets of the first mesh. The names of the sidesets in the first mesh are what the names that will remain in the outputted mesh.

!listing test/tests/meshgenerators/stitched_mesh_generator/stitched_mesh_generator.i block=Mesh

!media media/mesh/stitched_mesh_out.png caption=Fig. 4: Resulting "stitched" mesh from combination of three square meshes.
Expand Down
36 changes: 36 additions & 0 deletions framework/include/meshgenerators/SideSetExtruderGenerator.h
@@ -0,0 +1,36 @@
//* 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"

#include "libmesh/mesh_generation.h"

/**
* Extrude a 1D, 2D, or 3D mesh outward within the same dimension
*/
class SideSetExtruderGenerator : public MeshGenerator
{
public:
static InputParameters validParams();

SideSetExtruderGenerator(const InputParameters & parameters);

std::unique_ptr<MeshBase> generate() override;

protected:
/// Mesh that comes from another generator
std::unique_ptr<MeshBase> * _build_mesh;

const MeshGeneratorName _original_input;
const RealVectorValue _extrusion_vector;
const unsigned int _num_layers;
const BoundaryName _sideset_name;
};
100 changes: 100 additions & 0 deletions framework/src/meshgenerators/SideSetExtruderGenerator.C
@@ -0,0 +1,100 @@
//* 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 "SideSetExtruderGenerator.h"
#include "CastUniquePointer.h"

registerMooseObject("MooseApp", SideSetExtruderGenerator);

InputParameters
SideSetExtruderGenerator::validParams()
{
InputParameters params = MeshGenerator::validParams();

params.addClassDescription("Takes a 1D or 2D mesh and extrudes the entire structure along the "
"specified axis increasing the dimensionality of the mesh.");

// list params
params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
params.addRequiredParam<RealVectorValue>("extrusion_vector",
"The direction and length of the extrusion");
params.addParam<unsigned int>("num_layers", 1, "The number of layers in the extruded mesh");
params.addRequiredParam<BoundaryName>("sideset",
"The side set (boundary) that will be extruded from");

return params;
}

SideSetExtruderGenerator::SideSetExtruderGenerator(const InputParameters & parameters)
: MeshGenerator(parameters),
_original_input(getParam<MeshGeneratorName>("input")),
_extrusion_vector(getParam<RealVectorValue>("extrusion_vector")),
_num_layers(getParam<unsigned int>("num_layers")),
_sideset_name(getParam<BoundaryName>("sideset"))
{
// constants needed only temporarily
const BoundaryName _EXTRUDED_BLOCK_NAME = "extruded_block";
const BoundaryName _SIDESET_TO_BE_STITCHED = "to_be_stitched";

// sub generators
{
auto params = _app.getFactory().getValidParams("LowerDBlockFromSidesetGenerator");

params.set<MeshGeneratorName>("input") = _original_input;
params.set<SubdomainName>("new_block_name") = _EXTRUDED_BLOCK_NAME;
params.set<std::vector<BoundaryName>>("sidesets") = {_sideset_name};

// generate lower dimensional mesh from the given sidesets
_build_mesh = &addMeshSubgenerator(
"LowerDBlockFromSidesetGenerator", name() + "_lowerDgeneration", params);
}

{
auto params = _app.getFactory().getValidParams("BlockToMeshConverterGenerator");

params.set<MeshGeneratorName>("input") = name() + "_lowerDgeneration";
params.set<std::vector<SubdomainName>>("target_blocks") = {_EXTRUDED_BLOCK_NAME};

// convert lower dimensional block to a separate mesh
_build_mesh =
&addMeshSubgenerator("BlockToMeshConverterGenerator", name() + "_blockToMesh", params);
}

{
auto params = _app.getFactory().getValidParams("MeshExtruderGenerator");

params.set<MeshGeneratorName>("input") = name() + "_blockToMesh";
params.set<RealVectorValue>("extrusion_vector") = _extrusion_vector;
params.set<unsigned int>("num_layers") = _num_layers;
params.set<std::vector<BoundaryName>>("bottom_sideset") = {_SIDESET_TO_BE_STITCHED};

// extrude the new, separate mesh into a higher dimension
_build_mesh = &addMeshSubgenerator("MeshExtruderGenerator", name() + "_extruder", params);
}

{
auto params = _app.getFactory().getValidParams("StitchedMeshGenerator");

// order of vector elements matters for this generator
// here order by: original mesh first, our custom mesh second
params.set<std::vector<MeshGeneratorName>>("inputs") = {_original_input, name() + "_extruder"};

params.set<std::vector<std::vector<std::string>>>("stitch_boundaries_pairs") = {
{_sideset_name, _SIDESET_TO_BE_STITCHED}};

// stitch the newly made high-dimensional mesh back to the original mesh
_build_mesh = &addMeshSubgenerator("StitchedMeshGenerator", name() + "_stitched", params);
}
}

std::unique_ptr<MeshBase>
SideSetExtruderGenerator::generate()
{
return dynamic_pointer_cast<MeshBase>(*_build_mesh);
}
Binary file not shown.
@@ -0,0 +1,32 @@
[Mesh]
# Note: don't change the parameters without also changing extrude_square,
# as they should be using identical file(s) in gold
[square]
type = GeneratedMeshGenerator
dim = 2
[]
[lowerDblock]
type = LowerDBlockFromSidesetGenerator
input = square
new_block_name = "extrusions0"
sidesets = "right"
[]
[separateMesh]
type = BlockToMeshConverterGenerator
input = lowerDblock
target_blocks = extrusions0
[]
[extrude]
type = MeshExtruderGenerator
input = separateMesh
num_layers = 3
extrusion_vector = '1 0.5 0'
bottom_sideset = 'new_bottom'
top_sideset = 'new_top'
[]
[stitch]
type = StitchedMeshGenerator
inputs = 'square extrude'
stitch_boundaries_pairs = 'right new_bottom'
[]
[]
@@ -0,0 +1,13 @@
[Mesh]
[cube]
type = GeneratedMeshGenerator
dim = 3
[]
[extrude_top]
type = SideSetExtruderGenerator
input = cube
sideset = 'top'
extrusion_vector = '3 3 3'
num_layers = 3
[]
[]
@@ -0,0 +1,13 @@
[Mesh]
[cube]
type = GeneratedMeshGenerator
dim = 3
[]
[extrude_top]
type = SideSetExtruderGenerator
input = cube
sideset = 'top'
extrusion_vector = '3 3 3'
num_layers = 3
[]
[]
@@ -0,0 +1,13 @@
[Mesh]
[file]
type = FileMeshGenerator
file = 3d_serrated_multiblock.e
[]
[extrude]
type = SideSetExtruderGenerator
input = file
sideset = '6'
extrusion_vector = '1 1 0.5'
num_layers = 3
[]
[]
@@ -0,0 +1,13 @@
[Mesh]
[file]
type = FileMeshGenerator
file = 3d_serrated_multiblock.e
[]
[extrude]
type = SideSetExtruderGenerator
input = file
sideset = '6'
extrusion_vector = '1 1 0.5'
num_layers = 3
[]
[]
@@ -0,0 +1,15 @@
[Mesh]
# Note: don't change the parameters without also changing extrude_square,
# as they should be using identical file(s) in gold
[square]
type = GeneratedMeshGenerator
dim = 2
[]
[extrude_right]
type = SideSetExtruderGenerator
input = square
sideset = 'right'
extrusion_vector = '1 0.5 0'
num_layers = 3
[]
[]
@@ -0,0 +1,15 @@
[Mesh]
# Note: don't change the parameters without also changing extrude_square,
# as they should be using identical file(s) in gold
[square]
type = GeneratedMeshGenerator
dim = 2
[]
[extrude_right]
type = SideSetExtruderGenerator
input = square
sideset = 'right'
extrusion_vector = '1 0.5 0'
num_layers = 3
[]
[]

0 comments on commit 72ead2f

Please sign in to comment.