https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SidesetAroundSubdomainUpdater.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 "DisplacedProblem.h"
12#include "Assembly.h"
13
14#include "libmesh/parallel_algebra.h"
15#include "libmesh/parallel_sync.h"
16
18
21{
23 params.addClassDescription("Sets up a boundary between inner_subdomains and outer_subdomains");
24 params.addParam<std::vector<SubdomainName>>("inner_subdomains",
25 "Subdomains that own the boundary");
26 params.addParam<std::vector<SubdomainName>>("outer_subdomains",
27 "Subdomains on the outside of the boundary");
28 params.addParam<BoundaryName>("mask_side",
29 "If specified, only add sides where this sideset exists.");
30 params.addParam<bool>("assign_outer_surface_sides",
31 true,
32 "Assign sides of elements im `inner_subdomains` that have no neighbor.");
33 params.addRequiredParam<BoundaryName>("update_sideset_name",
34 "The name of the sideset to be updated. If the boundary "
35 "does not exist it will be added to the system.");
36 params.renameParam(
37 "update_sideset_name", "update_boundary_name", "The boundary name which is updated.");
38 params.addParam<BoundaryID>("update_sideset_id",
40 "The ID of the sideset to be updated. If the boundary "
41 "does not exist it will be added to the system.");
42 params.renameParam(
43 "update_sideset_id", "update_boundary_id", "The boundary id which is updated.");
44 params.registerBase("MeshModifier");
45 params.addParam<bool>("verbose", false, "Whether to output some information during execution");
46 return params;
47}
48
50 : DomainUserObject(parameters),
51 _pid(_communicator.rank()),
52 _displaced_problem(_fe_problem.getDisplacedProblem().get()),
53 _neighbor_side(_assembly.neighborSide()),
54 _assign_outer_surface_sides(getParam<bool>("assign_outer_surface_sides")),
55 _boundary_name(getParam<BoundaryName>("update_boundary_name")),
56 _boundary_id(_mesh.getBoundaryID(_boundary_name)),
57 _mask_side(isParamValid("mask_side") ? _mesh.getBoundaryID(getParam<BoundaryName>("mask_side"))
58 : Moose::INVALID_BOUNDARY_ID),
59 _boundary_info(_mesh.getMesh().get_boundary_info()),
60 _displaced_boundary_info(
61 _displaced_problem ? &_displaced_problem->mesh().getMesh().get_boundary_info() : nullptr)
62{
63 // subdomains
64 const auto & inner_subdomains = getParam<std::vector<SubdomainName>>("inner_subdomains");
65 const auto & outer_subdomains = getParam<std::vector<SubdomainName>>("outer_subdomains");
66 for (const auto id : MooseMeshUtils::getSubdomainIDs(_mesh.getMesh(), inner_subdomains))
67 _inner_ids.insert(id);
68 for (const auto id : MooseMeshUtils::getSubdomainIDs(_mesh.getMesh(), outer_subdomains))
69 _outer_ids.insert(id);
70 std::set<SubdomainID> mesh_subdomains = _mesh.meshSubdomains();
71
72 for (const auto & id : _inner_ids)
73 if (mesh_subdomains.find(id) == mesh_subdomains.end())
74 paramError("inner_subdomains", "The block '", id, "' was not found in the mesh");
75 for (const auto & id : _outer_ids)
76 if (mesh_subdomains.find(id) == mesh_subdomains.end())
77 paramError("outer_subdomains", "The block '", id, "' was not found in the mesh");
78
79 // save boundary name
83 {
86 }
88 mooseDoOnce(
89 mooseWarning("The user has selected 'construct_node_list_from_side_list' as false, but "
90 "SidesetAroundSubdomainUpdate is building node lists from the side lists."));
91}
92
93void
94SidesetAroundSubdomainUpdater::executeOnExternalSide(const Elem * elem, unsigned int side)
95{
96 // we should add the sideset only of the current element is in the "inner" set _and_ the user set
97 // assign_surface_sides
98 if (_inner_ids.count(elem->subdomain_id()))
99 {
100 if (_assign_outer_surface_sides && !_boundary_info.has_boundary_id(elem, side, _boundary_id) &&
102 _boundary_info.has_boundary_id(elem, side, _mask_side)))
103 _add[_pid].emplace_back(elem->id(), side);
104 }
105 else
106 {
107 if (_boundary_info.has_boundary_id(elem, side, _boundary_id))
108 _remove[_pid].emplace_back(elem->id(), side);
109 }
110}
111
112void
118
119void
121 unsigned short int primary_side,
122 const Elem * secondary_elem)
123{
124 // undisplaced mesh
125 if (_inner_ids.count(primary_elem->subdomain_id()) &&
126 _outer_ids.count(secondary_elem->subdomain_id()))
127 {
128
129 // we are on an inner element facing an outer element->add boundary
130 if ((!_boundary_info.has_boundary_id(primary_elem, primary_side, _boundary_id)) &&
132 _boundary_info.has_boundary_id(primary_elem, primary_side, _mask_side)))
133 _add[primary_elem->processor_id()].emplace_back(primary_elem->id(), primary_side);
134 }
135 else
136 {
137 // we are on an outer, between inner elements, or other elements etc., delete
138 // the boundary for sure
139 if (_boundary_info.has_boundary_id(primary_elem, primary_side, _boundary_id))
140 _remove[primary_elem->processor_id()].emplace_back(primary_elem->id(), primary_side);
141 }
142}
143
144void
146{
147 _add.clear();
148 _remove.clear();
149}
150
151void
153{
154 const auto & sas = static_cast<const SidesetAroundSubdomainUpdater &>(uo);
155
156 for (const auto & [pid, list] : sas._add)
157 _add[pid].insert(_add[pid].end(), list.begin(), list.end());
158
159 for (const auto & [pid, list] : sas._remove)
160 _remove[pid].insert(_remove[pid].end(), list.begin(), list.end());
161}
162
163void
165{
166 const auto & mesh = _mesh.getMesh();
167 const auto * displaced_mesh =
169 if (getParam<bool>("verbose"))
170 {
171 unsigned int total_remove = 0, total_add = 0;
172 for (const auto & [pid, list] : _remove)
173 total_remove += _remove[pid].size();
174 for (const auto & [pid, list] : _add)
175 total_add += _add[pid].size();
176 comm().sum(total_remove);
177 comm().sum(total_add);
178
179 if (total_remove)
180 _console << "Removing " << total_remove << " sides from sideset " << _boundary_id
181 << std::endl;
182 if (total_add)
183 _console << "Adding " << total_add << " sides to sideset " << _boundary_id << std::endl;
184 }
185
186 auto add_functor = [this, &mesh, &displaced_mesh](const processor_id_type, const auto & sent_data)
187 {
188 for (auto & [elem_id, side] : sent_data)
189 {
190 _boundary_info.add_side(mesh.elem_ptr(elem_id), side, _boundary_id);
192 _displaced_boundary_info->add_side(displaced_mesh->elem_ptr(elem_id), side, _boundary_id);
193 }
194 };
195
196 auto remove_functor =
197 [this, &mesh, &displaced_mesh](const processor_id_type, const SideList & sent_data)
198 {
199 for (const auto & [elem_id, side] : sent_data)
200 {
201 const auto elem = mesh.elem_ptr(elem_id);
202 _boundary_info.remove_side(elem, side, _boundary_id);
203 for (const auto local_node_id : elem->nodes_on_side(side))
204 _boundary_info.remove_node(elem->node_ptr(local_node_id), _boundary_id);
206 {
207 const auto displaced_elem = displaced_mesh->elem_ptr(elem_id);
208 _displaced_boundary_info->remove_side(displaced_elem, side, _boundary_id);
209 for (const auto local_node_id : displaced_elem->nodes_on_side(side))
210 _displaced_boundary_info->remove_node(displaced_elem->node_ptr(local_node_id),
212 }
213 }
214 };
215
216 // communicate and act on remote and local changes
219
220 auto sync = [](auto & mesh)
221 {
222 mesh.getMesh().get_boundary_info().parallel_sync_side_ids();
223 mesh.getMesh().get_boundary_info().parallel_sync_node_ids();
224 mesh.getMesh().get_boundary_info().build_node_list_from_side_list();
225 mesh.update();
226 };
227 sync(_mesh);
229 sync(_displaced_problem->mesh());
230
231 // Reinit equation systems
233 /*intermediate_change=*/false, /*contract_mesh=*/false, /*clean_refinement_flags=*/false);
234}
boundary_id_type BoundaryID
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition MooseError.h:345
registerMooseObject("MooseApp", SidesetAroundSubdomainUpdater)
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
virtual MooseMesh & mesh() override
This user object allows related evaluations on elements, boundaries, internal sides,...
const Elem *const & _current_elem
The current element pointer (available during all execute functions)
MooseMesh & _mesh
the Moose mesh
const Elem *const & _neighbor_elem
The neighboring element (available during executeOnInternalSide() and executeOnInterface())
static InputParameters validParams()
const unsigned int & _current_side
Current side of the current element (available during executeOnInternalSide() and executeOnBoundary()...
virtual void meshChanged(bool intermediate_change, bool contract_mesh, bool clean_refinement_flags)
Update data after a mesh change.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
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.
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 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...
void registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System.
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 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:457
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition MooseMesh.C:3549
bool getConstructNodeListFromSideList()
Return construct node list from side list boolean.
Definition MooseMesh.h:1559
const std::set< SubdomainID > & meshSubdomains() const
Returns a read-only reference to the set of subdomains currently present in the Mesh.
Definition MooseMesh.C:3272
Update side sets around subdomains during a run, as subdomain IDs are changing.
const processor_id_type _pid
The MPI rank of this processor.
DisplacedProblem * _displaced_problem
Pointer to the displaced problem.
const bool _assign_outer_surface_sides
assign sideset to sides that have no neighbor elements
virtual void finalize() override
Finalize.
const BoundaryID _mask_side
If specified, only sides also on this boundary will be updated.
virtual void executeOnExternalSide(const Elem *, unsigned int) override
execute method that is called during ComputeUserObjects::onExternalSide
std::map< processor_id_type, SideList > _add
virtual void executeOnInternalSide() override
execute method that is called during ComputeUserObjects::onInternalSide
const unsigned int & _neighbor_side
Current side on the neighboring element.
BoundaryName _boundary_name
Boundary / sideset to update.
std::set< SubdomainID > _inner_ids
Subdomains on the two sides of the boundary.
std::vector< std::tuple< dof_id_type, unsigned short int > > SideList
virtual void threadJoin(const UserObject &) override
Must override.
virtual void initialize() override
Called before execute() is ever called so that data can be cleared.
SidesetAroundSubdomainUpdater(const InputParameters &parameters)
void processSide(const Elem *primary_elem, unsigned short int primary_side, const Elem *secondary_elem)
std::map< processor_id_type, SideList > _remove
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this user object.
Base class for user-specific data.
Definition UserObject.h:20
const Parallel::Communicator & _communicator
const Parallel::Communicator & comm() const
MeshBase & mesh
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.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
const BoundaryID INVALID_BOUNDARY_ID
Definition MooseTypes.C:22
void push_parallel_vector_data(const Communicator &comm, MapToVectors &&data, const ActionFunctor &act_on_data)