https://mooseframework.inl.gov
AddPeriodicBCAction.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 "AddPeriodicBCAction.h"
11 
12 #include "DisplacedProblem.h"
13 #include "FEProblem.h"
14 #include "MooseMesh.h"
15 #include "MooseVariableFE.h"
16 #include "NonlinearSystemBase.h"
17 #include "RelationshipManager.h"
18 
19 #include "libmesh/periodic_boundary.h"
20 
21 #include <optional>
22 
23 registerMooseAction("MooseApp", AddPeriodicBCAction, "add_periodic_bc");
24 registerMooseAction("MooseApp", AddPeriodicBCAction, "add_geometric_rm");
25 registerMooseAction("MooseApp", AddPeriodicBCAction, "add_algebraic_rm");
26 
29 {
32 
33  params.addParam<std::vector<VariableName>>("variable",
34  "Variable(s) to apply periodic boundary conditions "
35  "to; if unset, apply to all field variables.");
36 
37  params.addClassDescription("Action that adds periodic boundary conditions");
38 
39  return params;
40 }
41 
43  : Action(params), Moose::PeriodicBCHelper(static_cast<const Action &>(*this))
44 {
46 }
47 
48 void
50 {
51  if (_current_task == "add_geometric_rm")
52  // Tell the mesh to hold off on deleting remote elements because we need to wait for our
53  // periodic boundaries to be added
54  Action::_mesh->allowRemoteElementRemoval(false);
55 
56  if (_current_task == "add_algebraic_rm" && getPeriodicBoundaries().size())
57  {
58  auto rm_params = _factory.getValidParams("ElementSideNeighborLayers");
59 
60  rm_params.set<std::string>("for_whom") = "PeriodicBCs";
61  if (!_mesh)
62  mooseError("We should have added periodic boundaries and consequently we should have set the "
63  "_mesh by now");
64 
65  rm_params.set<MooseMesh *>("mesh") = _mesh;
66  // The default GhostPointNeighbors ghosting functor in libMesh handles the geometric ghosting
67  // of periodic boundaries for us, so we only need to handle the algebraic ghosting here
68  rm_params.set<Moose::RelationshipManagerType>("rm_type") =
70 
71  if (rm_params.areAllRequiredParamsValid())
72  {
73  auto rm_obj = _factory.create<RelationshipManager>(
74  "ElementSideNeighborLayers", "periodic_bc_ghosting_" + name(), rm_params);
75 
76  if (!_app.addRelationshipManager(rm_obj))
78  }
79  else
80  mooseError("Invalid initialization of ElementSideNeighborLayers");
81  }
82 
83  if (_current_task == "add_periodic_bc")
84  {
85  _mesh = &_problem->mesh();
86 
87  // Set _vars so that variables can be used in onSetupPeriodicBoundary
88  _vars = getVariables();
89  mooseAssert(_vars.size(), "Shouldn't run without variables");
90 
91  // Query the helper to determine the periodic boundaries, which will
92  // call onSetupPeriodicBoundary() for every periodic boundary
94 
95  if (!_mesh->isRegularOrthogonal())
96  {
97  std::ostringstream out;
98  out << "Periodicity information for the variables\n";
99  for (const auto & var_ptr : _vars)
100  out << " - " << var_ptr->name() << "\n";
101  out << "will only be stored in the system's DoF map, not on the MooseMesh";
102  mooseInfoRepeated(out.str());
103  }
104  }
105 }
106 
107 void
109 {
110  const auto is_regular_orthogonal = _mesh->isRegularOrthogonal();
111  for (const auto & var_ptr : _vars)
112  {
113  const auto sys_num = var_ptr->sys().number();
114  for (const auto component : make_range(var_ptr->count()))
115  {
116  const auto var_num = var_ptr->number() + component;
117 
118  // Set variable number in PeriodicBoundaryBase object
119  p.set_variable(var_num);
120 
121  // Add to MooseMesh to querying variable periodicity
122  if (is_regular_orthogonal)
123  _mesh->addPeriodicVariable(sys_num, var_num, p.myboundary, p.pairedboundary);
124 
125  // Add to dof maps for algebraic ghosting
126  const auto add_to_dof_map = [&p, &sys_num](auto & problem)
127  { problem.es().get_system(sys_num).get_dof_map().add_periodic_boundary(p); };
128  add_to_dof_map(*_problem);
129  if (auto displaced_problem = _problem->getDisplacedProblem())
130  add_to_dof_map(*displaced_problem);
131  }
132  }
133 }
134 
135 std::vector<const MooseVariableFieldBase *>
137 {
138  std::vector<VariableName> var_names;
139  // Variable is set, use it
140  if (isParamValid("variable"))
141  {
142  var_names = getParam<std::vector<VariableName>>("variable");
143  if (var_names.empty())
144  paramError("variable", "No variables are set to apply periodic boundaries to");
145  for (const auto & var_name : var_names)
146  {
147  if (_problem->hasScalarVariable(var_name))
148  paramError("variable",
149  "Variable '" + var_name +
150  "' is a scalar variable and does not support a periodic boundary condition");
151  if (!_problem->hasVariable(var_name))
152  paramError("variable", "Variable '" + var_name + "' not found");
153  if (_problem->getVariable(0, var_name).isFV())
154  paramError("variable",
155  "Variable '" + var_name +
156  "' is a finite volume variable and does not support a periodic boundary "
157  "condition.");
158  }
159  }
160  // Variable is not set, use all nonlinear variables that are non-scalar and non-FV
161  else
162  {
163  // We can't currently distinguish PeriodicBoundaries objects across
164  // multiple systems so we can't use vars across all systems
165  if (_problem->numSolverSystems() > 1)
166  mooseError("Parameter 'variable' must be specified when multiple solver systems exist");
167  const auto & nl = _problem->getNonlinearSystemBase(0);
168  var_names = nl.getVariableNames();
169  var_names.erase(std::remove_if(var_names.begin(),
170  var_names.end(),
171  [&nl](const auto & var_name)
172  {
173  return nl.hasScalarVariable(var_name) ||
174  nl.getVariable(0, var_name).isFV();
175  }),
176  var_names.end());
177  if (var_names.empty())
178  mooseError("There are no variables to apply periodic boundaries to");
179  }
180 
181  // Verify and collect variables
182  std::vector<const MooseVariableFieldBase *> vars;
183  vars.reserve(var_names.size());
184  std::optional<unsigned int> used_sys_num;
185  for (const auto & var_name : var_names)
186  {
187  const auto & var = _problem->getVariable(0, var_name);
188  const auto sys_num = var.sys().number();
189 
190  // Until we have a way to have separate PeriodicBoundaries objects for each systems,
191  // we can't do these in the same block
192  if (used_sys_num && *used_sys_num != sys_num)
193  paramError("variable",
194  "Variables were specified across multiple systems; this is not supported. Use a "
195  "separate [Periodic/BCs] block for each system.");
196  used_sys_num = sys_num;
197 
198  vars.push_back(&var);
199  }
200 
201  return vars;
202 }
void setupPeriodicBoundaries(FEProblemBase &problem)
Sets up the periodic boundaries.
unsigned int size(THREAD_ID tid=0) const
Return how many kernels we store in the current warehouse.
This Action adds a periodic boundary to the problem.
std::shared_ptr< DisplacedProblem > displaced_problem
RelationshipManagerType
Main types of Relationship Managers.
Definition: MooseTypes.h:1012
registerMooseAction("MooseApp", AddPeriodicBCAction, "add_periodic_bc")
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
Factory & _factory
The Factory associated with the MooseApp.
char ** vars
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, const InputParameters &parameters, THREAD_ID tid=0, bool print_deprecated=true)
Definition: Factory.C:142
boundary_id_type pairedboundary
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition: Factory.C:68
void addPeriodicVariable(const unsigned int sys_num, const unsigned int var_num, const BoundaryID primary, const BoundaryID secondary)
For "regular orthogonal" meshes, determine if variable var_num is periodic with respect to the primar...
Definition: MooseMesh.C:2229
void mooseInfoRepeated(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
Definition: MooseError.h:409
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::vector< const MooseVariableFieldBase * > getVariables() const
Helper for getting the variables to which periodic boundary conditions will be applied.
const libMesh::PeriodicBoundaries & getPeriodicBoundaries() const
Get the PeriodicBoundaries map produced in setupPeriodicBoundaries().
Base class for actions.
Definition: Action.h:34
virtual void act() override
Method to add objects to the simulation or perform other setup tasks.
std::vector< const MooseVariableFieldBase * > _vars
The variables to apply periodic boundary conditions to.
void set_variable(unsigned int var)
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
bool addRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Transfers ownership of a RelationshipManager to the application for lifetime management.
Definition: MooseApp.C:2718
static InputParameters validParams()
Definition: Action.C:26
void checkPeriodicParams() const
Checks the validity of the periodic boundary condition parameters.
AddPeriodicBCAction(const InputParameters &params)
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:93
const std::string & _current_task
The current action (even though we have separate instances for each action)
Definition: Action.h:172
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:385
bool isRegularOrthogonal()
Getter to query if the mesh was detected to be regular and orthogonal.
Definition: MooseMesh.h:1195
static InputParameters validParams()
void releaseSharedObjects(const MooseObject &moose_object, THREAD_ID tid=0)
Releases any shared resources created as a side effect of creating an object through the Factory::cre...
Definition: Factory.C:156
std::shared_ptr< MooseMesh > & _mesh
Definition: Action.h:174
RelationshipManagers are used for describing what kinds of non-local resources are needed for an obje...
OStreamProxy out
IntRange< T > make_range(T beg, T end)
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
static InputParameters validParams()
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...
std::shared_ptr< FEProblemBase > & _problem
Convenience reference to a problem this action works on.
Definition: Action.h:178
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
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
virtual void onSetupPeriodicBoundary(libMesh::PeriodicBoundaryBase &p) override
Overriden method from PeriodicBCHelper that is called on every periodic boundary, in which we will se...