https://mooseframework.inl.gov
PeriodicBCHelper.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 "PeriodicBCHelper.h"
11 
12 #include "DisplacedProblem.h"
13 #include "FEProblemBase.h"
15 #include "MooseObjectAction.h"
16 #include "MooseMesh.h"
17 
18 #include "libmesh/periodic_boundary.h"
19 #include "libmesh/ghost_point_neighbors.h"
20 
21 namespace Moose
22 {
25 {
26  auto params = emptyInputParameters();
27 
28  const MultiMooseEnum auto_direction("x=0 y=1 z=2");
29  params.addParam<MultiMooseEnum>(
30  "auto_direction",
31  auto_direction,
32  "If using a generated mesh, the dimension(s) you want to mark as periodic.");
33 
34  params.addParam<BoundaryName>("primary", "Boundary associated with the primary boundary.");
35  params.addParam<BoundaryName>("secondary", "Boundary associated with the secondary boundary.");
36  params.addParam<RealVectorValue>("translation",
37  "Vector that translates coordinates on the primary boundary to "
38  "coordinates on the secondary boundary.");
39  params.addParam<std::vector<std::string>>("transform_func",
40  "Functions that specify the transformation");
41  params.addParam<std::vector<std::string>>("inv_transform_func",
42  "Functions that specify the inverse transformation");
43  return params;
44 }
45 
46 PeriodicBCHelper::PeriodicBCHelper(const Action & action) : _action(action), _params(getParams()) {}
47 
48 void
50 {
51  if (_params.isParamValid("auto_direction"))
52  {
53  for (const auto & param :
54  {"primary", "secondary", "translation", "transform_func", "inv_transform_func"})
55  if (_params.isParamValid(param))
56  _params.paramError(param, "Should not be specified along with 'auto_direction'");
57  }
58  else if (!_params.isParamValid("primary") || !_params.isParamValid("secondary"))
60  "Either 'auto_direction' or both 'primary' and 'secondary' must be specified");
61 }
62 
63 void
65 {
66  mooseAssert(_periodic_boundaries.empty(), "Already set");
67 
68  // Setup paired sidesets to be able to call MooseMesh::getPairedBoundaryMapping()
69  if (!problem.mesh().hasDetectedPairedSidesets())
70  problem.mesh().detectPairedSidesets();
71 
72  if (_params.isParamValid("auto_direction"))
74  else
76 
77  mooseAssert(getPeriodicBoundaries().size(), "Shouldn't run without boundaries");
78 
79  const auto add_ghosting = [this](auto & problem)
80  {
81  auto & mesh = problem.mesh().getMesh();
82  auto functor = std::make_shared<libMesh::GhostPointNeighbors>(mesh);
83  functor->set_periodic_boundaries(&getPeriodicBoundaries());
84  mesh.add_ghosting_functor(functor);
85  };
86 
87  add_ghosting(problem);
88  if (const auto displaced_problem = problem.getDisplacedProblem())
89  add_ghosting(*displaced_problem);
90 }
91 
92 void
93 PeriodicBCHelper::addPeriodicBoundary(std::unique_ptr<libMesh::PeriodicBoundaryBase> p)
94 {
96 
97  _periodic_boundaries.emplace(p->myboundary, p->clone());
98  _periodic_boundaries.emplace(p->pairedboundary, p->clone(libMesh::PeriodicBoundaryBase::INVERSE));
99 }
100 
101 void
103 {
104  // If we are working with a parallel mesh then we're going to ghost all the boundaries
105  // everywhere because we don't know what we need...
106  if (mesh.isDistributedMesh() && !mesh.detectOrthogonalDimRanges())
107  _action.mooseError("Could not detect orthogonal dimension ranges for DistributedMesh.");
108 
109  for (const auto & dir : _params.get<MultiMooseEnum>("auto_direction"))
110  {
111  const int component = dir.id();
112  if (component > (cast_int<int>(mesh.dimension()) - 1))
113  _params.paramError("auto_direction",
114  MooseUtils::toLower(dir.name()),
115  "-dimension component not valid for ",
116  mesh.dimension(),
117  "D mesh");
118 
119  const auto boundary_ids = mesh.getPairedBoundaryMapping(component);
120  if (!boundary_ids)
121  _params.paramError("auto_direction",
122  "Couldn't auto-detect a paired boundary in the ",
123  MooseUtils::toLower(dir.name()),
124  "-direction");
125 
126  RealVectorValue v;
127  v(component) = mesh.dimensionWidth(component);
128 
129  auto p = std::make_unique<libMesh::PeriodicBoundary>(v);
130  p->myboundary = boundary_ids->first;
131  p->pairedboundary = boundary_ids->second;
132 
133  addPeriodicBoundary(std::move(p));
134  }
135 }
136 
137 void
139 {
140  auto & mesh = problem.mesh();
141  std::unique_ptr<libMesh::PeriodicBoundaryBase> p;
142 
143  if (const auto translation_ptr = _params.queryParam<RealVectorValue>("translation"))
144  p = std::make_unique<libMesh::PeriodicBoundary>(*translation_ptr);
145  else if (const auto fn_names_ptr = _params.queryParam<std::vector<std::string>>("transform_func"))
146  {
147  const auto inv_fn_names_ptr =
148  _params.queryParam<std::vector<std::string>>("inv_transform_func");
149  if (!inv_fn_names_ptr)
150  _params.paramError("transform_func", "Must also specify 'inv_transform_func'");
151  if (fn_names_ptr->size() != mesh.dimension())
153  "transform_func", "Must be the size of the mesh dimension ", mesh.dimension());
154  if (inv_fn_names_ptr->size() != mesh.dimension())
156  "inv_transform_func", "Must be the size of the mesh dimension ", mesh.dimension());
157 
158  p = std::make_unique<FunctionPeriodicBoundary>(problem, *fn_names_ptr, *inv_fn_names_ptr);
159  }
160  else
162  "You need to specify either 'auto_direction', 'translation', or 'transform_func'");
163 
164  const auto get_boundary = [this, &mesh](const auto & param) -> BoundaryID
165  {
166  if (const auto name_ptr = _params.queryParam<BoundaryName>(param))
167  {
168  if (const auto id = MooseMeshUtils::getBoundaryID(*name_ptr, mesh);
170  return id;
171  _params.paramError(param, "Boundary '", *name_ptr, "' does not exist in the mesh");
172  }
173  _action.mooseError("Parameter '", param, "' is required when 'auto_direction' is not set");
174  };
175  p->myboundary = get_boundary("primary");
176  p->pairedboundary = get_boundary("secondary");
177 
178  addPeriodicBoundary(std::move(p));
179 }
180 
181 const InputParameters &
183 {
184  if (const auto moa = dynamic_cast<const MooseObjectAction *>(&_action))
185  return moa->getObjectParams();
186  return _action.parameters();
187 }
188 }
void setupPeriodicBoundaries(FEProblemBase &problem)
Sets up the periodic boundaries.
bool hasDetectedPairedSidesets() const
Whether or not detectedPairedSidesets() has been called.
Definition: MooseMesh.h:999
std::shared_ptr< DisplacedProblem > displaced_problem
const BoundaryID INVALID_BOUNDARY_ID
Definition: MooseTypes.C:22
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
void setupManualPeriodicBoundaries(FEProblemBase &problem)
Internal method for setting up manual periodic boundaries via the "translation" and "transform_func" ...
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:131
MeshBase & mesh
void addPeriodicBoundary(std::unique_ptr< libMesh::PeriodicBoundaryBase >)
Internal helper for adding a periodic boundary.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void detectPairedSidesets()
This routine detects paired sidesets of a regular orthogonal mesh (.i.e.
Definition: MooseMesh.C:2028
PeriodicBCHelper(const Action &action)
const libMesh::PeriodicBoundaries & getPeriodicBoundaries() const
Get the PeriodicBoundaries map produced in setupPeriodicBoundaries().
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
Base class for actions.
Definition: Action.h:34
InputParameters emptyInputParameters()
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)
Gets the boundary ID associated with the given BoundaryName.
void paramError(const std::string &param, Args... args) const
Emits a parameter error prefixed with the parameter location and object information if available...
void checkPeriodicParams() const
Checks the validity of the periodic boundary condition parameters.
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3575
boundary_id_type BoundaryID
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:93
void setupAutoPeriodicBoundaries(MooseMesh &mesh)
Internal method for setting up periodic boundaries via the "auto_direction" param.
std::string toLower(std::string name)
Convert supplied string to lower case.
static InputParameters validParams()
const InputParameters & _params
The parameters used to create the periodic boundary.
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
const InputParameters & getParams() const
Internal method for getting the parameters by the owned action.
virtual MooseMesh & mesh() override
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:281
libMesh::PeriodicBoundaries _periodic_boundaries
The PeriodicBoundaries map, filled in setupPeriodicBoundaries()
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type...
const T * queryParam(const std::string &name) const
Query a parameter.
virtual void onSetupPeriodicBoundary(libMesh::PeriodicBoundaryBase &)
Entry-point for derived actions to extend the addition of a periodic boundary.
const Action & _action
The owning Action.
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.