https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SideSetsBetweenSubdomainsGenerator.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 "InputParameters.h"
12#include "MooseTypes.h"
13#include "MeshTraversingUtils.h"
14#include "MooseMeshUtils.h"
15#include "CastUniquePointer.h"
16
17#include "libmesh/remote_elem.h"
18
20
23{
25
26 params.renameParam("included_subdomains",
27 "primary_block",
28 "The primary set of blocks for which to draw a sideset between");
29 params.makeParamRequired<std::vector<SubdomainName>>("primary_block");
30 params.renameParam("included_neighbors",
31 "paired_block",
32 "The paired set of blocks for which to draw a sideset between");
33 params.makeParamRequired<std::vector<SubdomainName>>("paired_block");
34 params.addClassDescription("MeshGenerator that creates a sideset composed of the nodes located "
35 "between two or more subdomains.");
36
37 // TODO: Implement each of these in the generate() routine using utilities in SidesetGeneratorBase
38 params.suppressParameter<bool>("fixed_normal");
39 params.suppressParameter<bool>("include_only_external_sides");
40
41 return params;
42}
43
49
50std::unique_ptr<MeshBase>
52{
53 std::unique_ptr<MeshBase> mesh = std::move(_input);
54
55 // construct the FE object so we can compute normals of faces
56 setup(*mesh);
57
58 std::vector<boundary_id_type> boundary_ids =
60
61 // Get a reference to our BoundaryInfo object for later use
62 BoundaryInfo & boundary_info = mesh->get_boundary_info();
63
64 // Prepare to query about sides adjacent to remote elements if we're
65 // on a distributed mesh
66 const processor_id_type my_n_proc = mesh->n_processors();
67 const processor_id_type my_proc_id = mesh->processor_id();
68 typedef std::vector<std::pair<dof_id_type, unsigned int>> vec_type;
69 std::vector<vec_type> queries(my_n_proc);
70
71 // Request to compute normal vectors
72 const std::vector<Point> & face_normals = _fe_face->get_normals();
73
74 for (const auto & elem : mesh->active_element_ptr_range())
75 {
76 // We only need to loop over elements in the primary subdomain
79 continue;
80
81 for (const auto & side : make_range(elem->n_sides()))
82 {
83 const Elem * neighbor = elem->neighbor_ptr(side);
84
85 // On a replicated mesh, we add all subdomain sides ourselves.
86 // On a distributed mesh, we may have missed sides which
87 // neighbor remote elements. We should query any such cases.
88 if (neighbor == remote_elem)
89 {
90 queries[elem->processor_id()].push_back(std::make_pair(elem->id(), side));
91 }
92 else if (neighbor != NULL)
93 {
94 _fe_face->reinit(elem, side);
95 // We'll just use the normal of the first qp
96 const Point & face_normal = face_normals[0];
97 // Add the boundaries, if appropriate
98 if (elemSideSatisfiesRequirements(elem, side, *mesh, _normal, face_normal))
99 {
100 // Add the boundaries
101 if (_replace)
102 boundary_info.remove_side(elem, side);
103 for (const auto & boundary_id : boundary_ids)
104 boundary_info.add_side(elem, side, boundary_id);
105 }
106 }
107 }
108 }
109
110 if (!mesh->is_serial())
111 {
112 const auto queries_tag = mesh->comm().get_unique_tag(),
113 replies_tag = mesh->comm().get_unique_tag();
114
115 std::vector<Parallel::Request> side_requests(my_n_proc - 1), reply_requests(my_n_proc - 1);
116
117 // Make all requests
118 for (const auto & p : make_range(my_n_proc))
119 {
120 if (p == my_proc_id)
121 continue;
122
123 Parallel::Request & request = side_requests[p - (p > my_proc_id)];
124
125 mesh->comm().send(p, queries[p], request, queries_tag);
126 }
127
128 // Reply to all requests
129 std::vector<vec_type> responses(my_n_proc - 1);
130
131 for (const auto & p : make_range(uint(1), my_n_proc))
132 {
133 vec_type query;
134
135 Parallel::Status status(mesh->comm().probe(Parallel::any_source, queries_tag));
136 const processor_id_type source_pid = cast_int<processor_id_type>(status.source());
137
138 mesh->comm().receive(source_pid, query, queries_tag);
139
140 Parallel::Request & request = reply_requests[p - 1];
141
142 for (const auto & q : query)
143 {
144 const Elem * elem = mesh->elem_ptr(q.first);
145 const unsigned int side = q.second;
146 const Elem * neighbor = elem->neighbor_ptr(side);
147
148 if (neighbor != NULL)
149 {
150 _fe_face->reinit(elem, side);
151 // We'll just use the normal of the first qp
152 const Point & face_normal = _fe_face->get_normals()[0];
153 // Add the boundaries, if appropriate
154 if (elemSideSatisfiesRequirements(elem, side, *mesh, _normal, face_normal))
155 responses[p - 1].push_back(std::make_pair(elem->id(), side));
156 }
157 }
158
159 mesh->comm().send(source_pid, responses[p - 1], request, replies_tag);
160 }
161
162 // Process all incoming replies
163 for (processor_id_type p = 1; p != my_n_proc; ++p)
164 {
165 Parallel::Status status(this->comm().probe(Parallel::any_source, replies_tag));
166 const processor_id_type source_pid = cast_int<processor_id_type>(status.source());
167
168 vec_type response;
169
170 this->comm().receive(source_pid, response, replies_tag);
171
172 for (const auto & r : response)
173 {
174 const Elem * elem = mesh->elem_ptr(r.first);
175 const unsigned int side = r.second;
176
177 if (_replace)
178 boundary_info.remove_side(elem, side);
179 for (const auto & boundary_id : boundary_ids)
180 boundary_info.add_side(elem, side, boundary_id);
181 }
182 }
183
184 Parallel::wait(side_requests);
185 Parallel::wait(reply_requests);
186 }
187
188 for (const auto & i : make_range(boundary_ids.size()))
189 boundary_info.sideset_name(boundary_ids[i]) = _boundary_names[i];
190
191 mesh->unset_is_prepared();
192 return dynamic_pointer_cast<MeshBase>(mesh);
193}
registerMooseObject("MooseApp", SideSetsBetweenSubdomainsGenerator)
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void suppressParameter(const std::string &name)
This method suppresses an inherited parameter so that it isn't required or valid in the derived class...
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.
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 makeParamRequired(const std::string &name)
Changes the parameter to be required.
MeshGenerator that creates a sideset composed of the nodes located between two or more subdomains.
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
SideSetsBetweenSubdomainsGenerator(const InputParameters &parameters)
void setup(MeshBase &mesh)
This method is used to construct the FE object so we can compute normals of faces.
std::unique_ptr< libMesh::FEBase > _fe_face
std::vector< BoundaryName > _boundary_names
The list of new boundary names.
Point _normal
if specified, then faces are only added if their normal is close to this
static InputParameters validParams()
bool elemSideSatisfiesRequirements(const Elem *const elem, const unsigned int side, const MeshBase &mesh, const Point &normal, const Point &face_normal)
Determines whether the given element's side satisfies the following parameters: include_only_external...
const bool _check_subdomains
whether to check subdomain ids of the element in the (element, side, boundary id) tuple when adding s...
std::unique_ptr< MeshBase > & _input
the mesh to add the sidesets to
const bool _replace
Whether or not to remove the old sidesets (all of them, if any) when adding sidesets.
std::vector< subdomain_id_type > _included_subdomain_ids
A list of included subdomain ids that the side has to be part of, extracted from the included_subdoma...
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
const Parallel::Communicator & comm() const
query_obj query
MeshBase & mesh
bool elementSubdomainIdInList(const Elem *const elem, const std::vector< subdomain_id_type > &subdomain_id_list)
Determines whether the given element's subdomain id is in the given subdomain_id_list.
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.