16 #include "libmesh/mesh.h" 17 #include "libmesh/remote_elem.h" 18 #include "libmesh/point.h" 19 #include "libmesh/fe_base.h" 28 params.
addRequiredParam<MeshGeneratorName>(
"input",
"The mesh we want to modify");
30 "new_boundary",
"The list of boundary IDs to create on the supplied subdomain");
32 "The blocks around which to create sidesets");
34 "If supplied, only faces with normal equal to this, up to " 35 "normal_tol, will be added to the sidesets specified");
36 params.
addParam<
bool>(
"external_only",
false,
"Only apply the sideset to external boundaries");
39 "normal_tol>=0 & normal_tol<=2",
40 "If normal is supplied then faces are " 41 "only added if face_normal.normal_hat >= " 42 "1 - normal_tol, where normal_hat = " 46 "Adds element faces that are on the exterior of the given block to the sidesets specified");
54 _input(getMesh(
"input")),
55 _boundary_names(getParam<
std::vector<BoundaryName>>(
"new_boundary")),
56 _using_normal(isParamValid(
"normal")),
57 _external_only(getParam<bool>(
"external_only")),
58 _normal_tol(getParam<
Real>(
"normal_tol")),
59 _normal(_using_normal ? getParam<Point>(
"normal") : Point())
64 mooseAssert(
_normal.norm() >= 1E-5,
"Normal is zero");
69 std::unique_ptr<MeshBase>
72 std::unique_ptr<MeshBase>
mesh = std::move(
_input);
74 std::vector<SubdomainName> block_names = getParam<std::vector<SubdomainName>>(
"block");
76 for (
const auto &
name : block_names)
78 paramError(
"block",
"The block '",
name,
"' was not found in the mesh");
81 std::set<subdomain_id_type> block_ids(blocks.begin(), blocks.end());
85 std::vector<boundary_id_type> boundary_ids =
91 bool add_to_bdy =
true;
94 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
100 typedef std::vector<std::pair<dof_id_type, unsigned int>> vec_type;
101 std::vector<vec_type> queries(my_n_proc);
104 for (
const auto & elem :
mesh->active_element_ptr_range())
109 if (block_ids.count(curr_subdomain) == 0)
112 for (
unsigned int side = 0; side < elem->n_sides(); ++side)
114 const Elem * neighbor = elem->neighbor_ptr(side);
121 queries[elem->processor_id()].push_back(std::make_pair(elem->id(), side));
123 else if (neighbor ==
nullptr ||
129 const std::vector<Point> & normals =
_fe_face->get_normals();
131 face_normal = normals[0];
137 for (
const auto & boundary_id : boundary_ids)
138 boundary_info.add_side(elem, side, boundary_id);
143 if (!
mesh->is_serial())
145 const auto queries_tag =
mesh->comm().get_unique_tag(),
146 replies_tag =
mesh->comm().get_unique_tag();
148 std::vector<Parallel::Request> side_requests(my_n_proc - 1), reply_requests(my_n_proc - 1);
156 Parallel::Request &
request = side_requests[p - (p > my_proc_id)];
158 mesh->comm().send(p, queries[p],
request, queries_tag);
162 std::vector<vec_type> responses(my_n_proc - 1);
168 Parallel::Status
status(
mesh->comm().probe(Parallel::any_source, queries_tag));
171 mesh->comm().receive(source_pid,
query, queries_tag);
173 Parallel::Request &
request = reply_requests[p - 1];
175 for (
const auto & q :
query)
177 const Elem * elem =
mesh->elem_ptr(q.first);
178 const unsigned int side = q.second;
179 const Elem * neighbor = elem->neighbor_ptr(side);
181 if (neighbor ==
nullptr ||
182 block_ids.count(neighbor->subdomain_id()) ==
187 const std::vector<Point> & normals =
_fe_face->get_normals();
189 face_normal = normals[0];
195 responses[p - 1].push_back(std::make_pair(elem->id(), side));
199 mesh->comm().send(source_pid, responses[p - 1],
request, replies_tag);
205 Parallel::Status
status(this->
comm().probe(Parallel::any_source, replies_tag));
210 this->
comm().
receive(source_pid, response, replies_tag);
212 for (
const auto & r : response)
214 const Elem * elem =
mesh->elem_ptr(r.first);
215 const unsigned int side = r.second;
217 for (
const auto & boundary_id : boundary_ids)
218 boundary_info.add_side(elem, side, boundary_id);
222 Parallel::wait(side_requests);
223 Parallel::wait(reply_requests);
227 for (
unsigned int i = 0; i < boundary_ids.size(); ++i)
230 mesh->set_isnt_prepared();
SideSetsAroundSubdomainGenerator(const InputParameters ¶meters)
std::vector< BoundaryName > _boundary_names
names of the sidesets to which the faces will be added
Point _normal
if specified, then faces are only added if their normal is close to this
const Parallel::Communicator & comm() const
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.
std::vector< subdomain_id_type > getSubdomainIDs(const libMesh::MeshBase &mesh, const std::vector< SubdomainName > &subdomain_name)
Get the associated subdomainIDs for the subdomain names that are passed in.
virtual const std::string & name() const
Get the name of the class.
uint8_t processor_id_type
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
Real _normal_tol
if normal is specified, then faces are only added if face_normal.normal_hat <= 1 - normal_tol where n...
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
std::unique_ptr< FEBase > _fe_face
bool hasSubdomainName(MeshBase &input_mesh, const SubdomainName &name)
Whether a particular subdomain name exists in the mesh.
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
void paramError(const std::string ¶m, 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()
static InputParameters validParams()
const bool _external_only
Only apply the sideset to external boundaries.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
registerMooseObject("MooseApp", SideSetsAroundSubdomainGenerator)
bool _using_normal
true if only faces close to "normal" will be added
std::unique_ptr< MeshBase > & _input
Adds the faces on the boundary of given block to the sidesets specified by "boundary" Optionally...
void setup(MeshBase &mesh)
This method is used to construct the FE object so we can compute normals of faces.
const RemoteElem * remote_elem