https://mooseframework.inl.gov
XYMeshLineCutter.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "XYMeshLineCutter.h"
12 #include "MooseMeshUtils.h"
13 
14 #include "libmesh/mesh_modification.h"
15 
16 // C++ includes
17 #include <cmath>
18 
20 
23 {
25 
26  MooseEnum cutting_type("CUT_ELEM_TRI MOV_NODE", "CUT_ELEM_TRI");
27  params.addParam<MooseEnum>(
28  "cutting_type",
29  cutting_type,
30  "Which method is to be used to cut the input mesh. 'CUT_ELEM_TRI' is the recommended method "
31  "but it may cause fine elements near the cutting line, while 'MOV_NODE' deforms subdomain "
32  "boundaries if they are not perpendicular to the cutting line.");
33 
34  params.addRequiredParam<MeshGeneratorName>("input", "The input mesh that needs to be trimmed.");
35  params.addRequiredParam<std::vector<Real>>(
36  "cut_line_params",
37  "Cutting line parameters, which are a, b, and c in line equation a*x+b*y+c=0. Note that "
38  "a*x+b*y+c>0 part is being removed.");
40  "new_boundary_id", "Boundary id to be assigned to the boundary formed by the cutting.");
41  params.addParam<boundary_id_type>("input_mesh_external_boundary_id",
42  "Boundary id of the external boundary of the input mesh.");
43  params.addParam<std::vector<boundary_id_type>>(
44  "other_boundaries_to_conform",
45  "IDs of the other boundaries that need to be conformed to during nodes moving.");
46 
47  params.addParam<SubdomainName>(
48  "tri_elem_subdomain_name_suffix",
49  "trimmer_tri",
50  "Suffix to the block name used for quad elements that are trimmed/converted into "
51  "triangular elements to avert degenerate quad elements");
53  "tri_elem_subdomain_shift",
54  "Customized id shift to define subdomain ids of the converted triangular elements.");
55  params.addParam<bool>(
56  "improve_tri_elements", false, "Whether to improve TRI3 elements after CUT_ELEM_TRI method.");
57 
58  params.addClassDescription(
59  "This XYMeshLineCutter object is designed to trim the input mesh by removing all the "
60  "elements on one side of a given straight line with special processing on the elements "
61  "crossed by the cutting line to ensure a smooth cross-section.");
62 
63  return params;
64 }
65 
67  : MeshGenerator(parameters),
68  _cutting_type(getParam<MooseEnum>("cutting_type").template getEnum<CutType>()),
69  _input_name(getParam<MeshGeneratorName>("input")),
70  _cut_line_params(getParam<std::vector<Real>>("cut_line_params")),
71  _new_boundary_id(getParam<boundary_id_type>("new_boundary_id")),
72  _input_mesh_external_boundary_id(
73  isParamValid("input_mesh_external_boundary_id")
74  ? getParam<boundary_id_type>("input_mesh_external_boundary_id")
76  _other_boundaries_to_conform(
77  isParamValid("other_boundaries_to_conform")
78  ? getParam<std::vector<boundary_id_type>>("other_boundaries_to_conform")
79  : std::vector<boundary_id_type>()),
80  _tri_elem_subdomain_name_suffix(getParam<SubdomainName>("tri_elem_subdomain_name_suffix")),
81  _tri_elem_subdomain_shift(isParamValid("tri_elem_subdomain_shift")
82  ? getParam<subdomain_id_type>("tri_elem_subdomain_shift")
84  _improve_tri_elements(getParam<bool>("improve_tri_elements")),
85  _input(getMeshByName(_input_name))
86 {
87  if (_cut_line_params.size() != 3)
88  paramError("cut_line_params", "this parameter must have three elements.");
91  paramError("cut_line_params", "At lease one of the first two elements must be non-zero.");
93  paramError("improve_tri_elements",
94  "This parameter is not supported when 'MOV_NODE' method is selected as "
95  "'cutting_type'.");
98  paramError(
99  "input_mesh_external_boundary_id",
100  "This parameter must be provided if 'MOV_NODE' method is selected as 'cutting_type'.");
101 }
102 
103 std::unique_ptr<MeshBase>
105 {
106  auto replicated_mesh_ptr = dynamic_cast<ReplicatedMesh *>(_input.get());
107  if (!replicated_mesh_ptr)
108  paramError("input", "Input is not a replicated mesh, which is required");
109  if (*(replicated_mesh_ptr->elem_dimensions().begin()) != 2 ||
110  *(replicated_mesh_ptr->elem_dimensions().rbegin()) != 2)
111  paramError("input", "Only 2D meshes are supported.");
112 
113  // Check that the input boundaries are part of the mesh
114  if (isParamValid("input_mesh_external_boundary_id"))
116  paramError("input_mesh_external_boundary_id", "Boundary must exist in input mesh");
117 
118  // Check that the other boundaries to conform to are part of the mesh
119  if (isParamValid("other_boundaries_to_conform"))
120  for (const auto bid : _other_boundaries_to_conform)
121  if (!MooseMeshUtils::hasBoundaryID(*replicated_mesh_ptr, bid))
122  paramError("other_boundaries_to_conform",
123  "Boundary '" + std::to_string(bid) + "' must exist in input mesh");
124 
125  ReplicatedMesh & mesh = *replicated_mesh_ptr;
126  // Subdomain ID for TRI elements arising of QUAD element cuts must be new
127  std::set<subdomain_id_type> subdomain_ids_set;
128  mesh.subdomain_ids(subdomain_ids_set);
129  const subdomain_id_type max_subdomain_id = *subdomain_ids_set.rbegin();
130  const subdomain_id_type block_id_to_remove = max_subdomain_id + 1;
131  const subdomain_id_type tri_subdomain_id_shift =
132  _tri_elem_subdomain_shift == Moose::INVALID_BLOCK_ID ? max_subdomain_id + 2
134 
135  // Use a unique new boundary id as the temporary boundary id for _new_boundary_id
136  // This help prevent issues when _new_boundary_id is already used in the mesh
138 
140  {
141  try
142  {
145  tri_subdomain_id_shift,
147  block_id_to_remove,
148  new_boundary_id_tmp,
150  }
151  catch (MooseException & e)
152  {
153  if (((std::string)e.what()).compare("The new subdomain name already exists in the mesh.") ==
154  0)
155  paramError("tri_elem_subdomain_name_suffix", e.what());
156  else
157  mooseError("In XYMeshLineCutter with 'CUT_ELEM_TRI' mode, " + (std::string)e.what());
158  }
159  }
160  else
161  {
162  try
163  {
166  block_id_to_remove,
167  subdomain_ids_set,
168  new_boundary_id_tmp,
171  }
172  catch (MooseException & e)
173  {
174  if (((std::string)e.what())
175  .compare("The input mesh has degenerate quad element before trimming.") == 0)
176  paramError("input", e.what());
177  else if (((std::string)e.what())
178  .compare("The new subdomain name already exists in the mesh.") == 0)
179  paramError("tri_elem_subdomain_name_suffix", e.what());
180  else
181  mooseError("In XYMeshLineCutter with 'MOV_NODE' mode, " + (std::string)e.what());
182  }
184  mesh, subdomain_ids_set, tri_subdomain_id_shift, _tri_elem_subdomain_name_suffix);
185  }
186 
187  // Then rename the temporary boundary id to _new_boundary_id
188  MeshTools::Modification::change_boundary_id(mesh, new_boundary_id_tmp, _new_boundary_id);
189 
190  mesh.prepare_for_use();
191  return std::move(_input);
192 }
void lineRemoverCutElem(libMesh::ReplicatedMesh &mesh, const std::vector< Real > &cut_line_params, const dof_id_type tri_subdomain_id_shift, const SubdomainName tri_elem_subdomain_name_suffix, const subdomain_id_type block_id_to_remove, const boundary_id_type new_boundary_id, const bool improve_boundary_tri_elems=false)
Trim the 2D mesh by removing all the elements on one side of the given line.
registerMooseObject("MooseApp", XYMeshLineCutter)
virtual const char * what() const
Get out the error message.
const bool _improve_tri_elements
Whether to improve TRI3 elements after CUT_ELEM_TRI method.
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
Definition: MooseUtils.h:380
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
const boundary_id_type _new_boundary_id
Boundary id to be assigned to the boundary formed by the cutting.
const BoundaryID INVALID_BOUNDARY_ID
Definition: MooseTypes.C:22
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void lineRemoverMoveNode(libMesh::ReplicatedMesh &mesh, const std::vector< Real > &bdry_pars, const subdomain_id_type block_id_to_remove, const std::set< subdomain_id_type > &subdomain_ids_set, const boundary_id_type trimming_section_boundary_id, const boundary_id_type external_boundary_id, const std::vector< boundary_id_type > &other_boundaries_to_conform=std::vector< boundary_id_type >(), const bool assign_ext_to_new=false, const bool side_to_remove=true)
Removes all the elements on one side of a given line and deforms the elements intercepted by the line...
enum XYMeshLineCutter::CutType _cutting_type
bool hasBoundaryID(const MeshBase &input_mesh, const BoundaryID id)
Whether a particular boundary ID exists in the mesh.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
const SubdomainID INVALID_BLOCK_ID
Definition: MooseTypes.C:20
XYMeshLineCutter(const InputParameters &parameters)
int8_t boundary_id_type
std::unique_ptr< MeshBase > & _input
Reference to input mesh pointer.
static InputParameters validParams()
const boundary_id_type _input_mesh_external_boundary_id
Boundary id of the external boundary of the input mesh (only needed for MOV_NODE method) ...
bool quasiTriElementsFixer(libMesh::ReplicatedMesh &mesh, const std::set< subdomain_id_type > &subdomain_ids_set, const subdomain_id_type tri_elem_subdomain_shift=Moose::INVALID_BLOCK_ID, const SubdomainName tri_elem_subdomain_name_suffix="tri")
Fixes degenerate QUAD elements created by the hexagonal mesh trimming by converting them into TRI ele...
CutType
Method to cut the input mesh.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
const std::vector< boundary_id_type > _other_boundaries_to_conform
IDs of the other boundaries that need to be conformed to during nodes moving (only needed for MOV_NOD...
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
static InputParameters validParams()
Definition: MeshGenerator.C:23
const SubdomainName _tri_elem_subdomain_name_suffix
SubdomainName suffix used to rename the converted triangular elements.
Provides a way for users to bail out of the current solve.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const subdomain_id_type _tri_elem_subdomain_shift
Customized id shift to define subdomain ids of the converted triangular elements. ...
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
This XYMeshLineCutter object is designed to trim the input mesh by removing all the elements on one s...
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
const std::vector< Real > _cut_line_params
Cutting line parameters, which are a, b, and c in line equation a*x+b*y+c=0. Note that a*x+b*y+c>0 pa...
BoundaryID getNextFreeBoundaryID(MeshBase &input_mesh)
Checks input mesh and returns the largest boundary ID in the mesh plus one, which is a boundary ID in...
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:32