https://mooseframework.inl.gov
OrientSurfaceMeshGenerator.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 
11 #include "Parser.h"
12 #include "InputParameters.h"
13 #include "CastUniquePointer.h"
14 
15 #include "libmesh/fe_base.h"
16 #include "libmesh/mesh_generation.h"
17 #include "libmesh/mesh.h"
18 #include "libmesh/string_to_enum.h"
19 #include "libmesh/quadrature_gauss.h"
20 #include "libmesh/point_locator_base.h"
21 #include "libmesh/distributed_mesh.h"
22 #include "libmesh/elem.h"
23 
24 #include <typeinfo>
25 
27 
30 {
32 
33  // NOTE: libmesh tetrahedralization code actually has a clever heuristic
34  // to re-orient elements starting from the known orientation of the "bottom-most"
35  // surface element. We could import that logic here, once we identify and separate connected
36  // (contiguous) components of the mesh.
37 
38  // Which elements to apply the change on
39  params.setDocString(
40  "included_subdomains",
41  "Subdomain names or ids for the elements that may have their normal modified.");
42 
43  // How to set the normal
44  params.renameParam("normal",
45  "normal_to_align_with",
46  "Direction vector that element normals should be pointing in the same "
47  "direction as (dot product > 0)");
48  params.addParam<std::vector<dof_id_type>>(
49  "element_ids_to_flood_from",
50  "IDs of elements to start flooding and changing the subdomains from");
51 
52  // This mesh generator does not modify the subdomains
53  params.suppressParameter<std::vector<SubdomainName>>("new_subdomain");
54  // This mesh generator is specifically intended to flip normals
55  params.set<bool>("flip_inverted_normals") = true;
56  params.suppressParameter<bool>("flip_inverted_normals");
57  params.set<bool>("consider_flipped_normals") = true;
58  params.set<bool>("_using_normal") = true;
59 
60  params.addClassDescription("Change the orientation of (part of) the surface mesh.");
61  return params;
62 }
63 
65  : SurfaceMeshGeneratorBase(parameters), _num_flipped(0)
66 {
67  if (!isParamValid("element_ids_to_flood_from") && !isParamSetByUser("normal_to_align_with"))
68  paramError("normal_to_align_with",
69  "Either a 'normal_to_align_with' or 'element_ids_to_flood_from' must be specified "
70  "to select the behavior of this mesh generator.");
71 }
72 
73 std::unique_ptr<MeshBase>
75 {
76  std::unique_ptr<MeshBase> mesh = std::move(_input);
77  setup(*mesh);
78 
79  auto & binfo = mesh->get_boundary_info();
80  bool normal_is_input = isParamSetByUser("normal_to_align_with");
81 
82  if (!isParamValid("element_ids_to_flood_from"))
83  // We'll need to loop over all of the elements to adjust normals with the fixed normal option
84  for (auto & elem : mesh->element_ptr_range())
85  {
86  // Nothing to do with edges or 3D elements
87  if (elem->dim() != 2)
88  continue;
89 
90  // Check if element should be used to paint from
91  if (_included_subdomain_ids.size() &&
94  elem->subdomain_id()) == _included_subdomain_ids.end())
95  continue;
96 
97  // Compute the normal
98  const auto normal = get2DElemNormal(elem);
99 
100  if (normal * _normal < 0)
101  {
102  elem->flip(&binfo);
103  _num_flipped++;
104  }
105  }
106  else
107  // We'll flood and re-adjust orientations starting from a few given elements
108  // NOTE: user's responsibility to make sure these surface elements' orientations are consistent
109  for (const auto eid : getParam<std::vector<dof_id_type>>("element_ids_to_flood_from"))
110  {
111  auto elem = mesh->elem_ptr(eid);
112 
113  // Nothing to do with edges or 3D elements
114  if (elem->dim() != 2)
115  continue;
116 
117  // Compute the normal
118  const auto normal = normal_is_input ? _normal : get2DElemNormal(elem);
119 
120  flood(elem, normal, *elem, elem->subdomain_id(), *mesh);
121  }
122 
123  if (_num_flipped)
124  _console << "Flipped the orientation of " << _num_flipped << " surface elements." << std::endl;
125 
126  return dynamic_pointer_cast<MeshBase>(mesh);
127 }
void renameParam(const std::string &old_name, const std::string &new_name, const std::string &new_docstring)
Rename a parameter and provide a new documentation string.
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
void setup(MeshBase &mesh)
Sets up various data structures.
void flood(Elem *const elem, const Point &normal, const Elem &starting_elem, const subdomain_id_type &sub_id, MeshBase &mesh)
This method implements a recursive flood routine to paint (applying an operation) to elements on mesh...
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 ...
Definition: MooseBase.h:467
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition: MooseBase.h:416
void setDocString(const std::string &name, const std::string &doc)
Set the doc string of a parameter.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
OrientSurfaceMeshGenerator(const InputParameters &parameters)
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
Point get2DElemNormal(const Elem *const elem) const
Get the normal of the 2D element.
void suppressParameter(const std::string &name)
This method suppresses an inherited parameter so that it isn&#39;t required or valid in the derived class...
Point _normal
if specified, then surface elements are only considered if their normal is close to this ...
static InputParameters validParams()
unsigned int _num_flipped
Keeps track of the number of element orientation flips, for output purposes.
This class will re-orient surface elements based on user-specified settings.
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...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:209
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
registerMooseObject("MooseApp", OrientSurfaceMeshGenerator)
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition: MooseBase.h:215
static InputParameters validParams()
std::unique_ptr< MeshBase > & _input
the mesh to add the subdomains to
std::vector< subdomain_id_type > _included_subdomain_ids
A list of included subdomain ids that the element has to be priorly a part of, extracted from the &#39;in...