www.mooseframework.org
AddPeriodicBCAction.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 // MOOSE includes
13 #include "DisplacedProblem.h"
14 #include "FEProblem.h"
16 #include "GeneratedMesh.h"
17 #include "InputParameters.h"
18 #include "MooseMesh.h"
19 #include "MooseVariableFE.h"
20 #include "NonlinearSystem.h"
21 #include "RelationshipManager.h"
22 
23 #include "libmesh/periodic_boundary.h" // translation PBCs provided by libmesh
24 
25 registerMooseAction("MooseApp", AddPeriodicBCAction, "add_periodic_bc");
26 registerMooseAction("MooseApp", AddPeriodicBCAction, "add_geometric_rm");
27 
28 template <>
31 {
33  params.addParam<std::vector<std::string>>("auto_direction",
34  "If using a generated mesh, you can "
35  "specifiy just the dimension(s) you "
36  "want to mark as periodic");
37 
38  params.addParam<BoundaryName>("primary", "Boundary ID associated with the primary boundary.");
39  params.addParam<BoundaryName>("secondary", "Boundary ID associated with the secondary boundary.");
40  params.addParam<RealVectorValue>("translation",
41  "Vector that translates coordinates on the "
42  "primary boundary to coordinates on the "
43  "secondary boundary.");
44  params.addParam<std::vector<std::string>>("transform_func",
45  "Functions that specify the transformation");
46  params.addParam<std::vector<std::string>>("inv_transform_func",
47  "Functions that specify the inverse transformation");
48 
49  params.addParam<std::vector<VariableName>>("variable", "Variable for the periodic boundary");
50  return params;
51 }
52 
54 
55 void
56 AddPeriodicBCAction::setPeriodicVars(PeriodicBoundaryBase & p,
57  const std::vector<VariableName> & var_names)
58 {
59  NonlinearSystemBase & nl = _problem->getNonlinearSystemBase();
60  const std::vector<VariableName> * var_names_ptr;
61 
62  // If var_names is empty - then apply this periodic condition to all variables in the system
63  if (var_names.empty())
64  var_names_ptr = &nl.getVariableNames();
65  else
66  var_names_ptr = &var_names;
67 
68  for (const auto & var_name : *var_names_ptr)
69  {
70  if (!nl.hasScalarVariable(var_name))
71  {
72  unsigned int var_num = nl.getVariable(0, var_name).number();
73  p.set_variable(var_num);
74  _mesh->addPeriodicVariable(var_num, p.myboundary, p.pairedboundary);
75  }
76  }
77 }
78 
79 bool
81 {
82  auto displaced_problem = _problem->getDisplacedProblem();
83 
84  if (isParamValid("auto_direction"))
85  {
86  // If we are working with a parallel mesh then we're going to ghost all the boundaries
87  // everywhere because we don't know what we need...
88  if (_mesh->isDistributedMesh())
89  {
90  const std::set<BoundaryID> & ids = _mesh->meshBoundaryIds();
91  for (const auto & bid : ids)
92  _problem->addGhostedBoundary(bid);
93 
94  _problem->ghostGhostedBoundaries();
95 
96  bool is_orthogonal_mesh = _mesh->detectOrthogonalDimRanges();
97 
98  // If we can't detect the orthogonal dimension ranges for this
99  // Mesh, then auto_direction periodicity isn't going to work.
100  if (!is_orthogonal_mesh)
101  mooseError("Could not detect orthogonal dimension ranges for DistributedMesh.");
102  }
103 
104  NonlinearSystemBase & nl = _problem->getNonlinearSystemBase();
105  std::vector<std::string> auto_dirs = getParam<std::vector<std::string>>("auto_direction");
106 
107  int dim_offset = _mesh->dimension() - 2;
108  for (const auto & dir : auto_dirs)
109  {
110  int component = -1;
111  if (dir == "X" || dir == "x")
112  component = 0;
113  else if (dir == "Y" || dir == "y")
114  {
115  if (dim_offset < 0)
116  mooseError("Cannot wrap 'Y' direction when using a 1D mesh");
117  component = 1;
118  }
119  else if (dir == "Z" || dir == "z")
120  {
121  if (dim_offset <= 0)
122  mooseError("Cannot wrap 'Z' direction when using a 1D or 2D mesh");
123  component = 2;
124  }
125 
126  if (component >= 0)
127  {
128  const std::pair<BoundaryID, BoundaryID> * boundary_ids =
129  _mesh->getPairedBoundaryMapping(component);
130  RealVectorValue v;
131  v(component) = _mesh->dimensionWidth(component);
132  PeriodicBoundary p(v);
133 
134  if (boundary_ids == NULL)
135  mooseError(
136  "Couldn't auto-detect a paired boundary for use with periodic boundary conditions");
137 
138  p.myboundary = boundary_ids->first;
139  p.pairedboundary = boundary_ids->second;
140  setPeriodicVars(p, getParam<std::vector<VariableName>>("variable"));
141  nl.dofMap().add_periodic_boundary(p);
142  if (displaced_problem)
143  displaced_problem->nlSys().dofMap().add_periodic_boundary(p);
144  }
145  }
146  return true;
147  }
148  return false;
149 }
150 
151 void
153 {
154  if (_current_task == "add_geometric_rm")
155  {
156  auto rm_params = _factory.getValidParams("ElementSideNeighborLayers");
157 
158  rm_params.set<std::string>("for_whom") = "PeriodicBCs";
159  rm_params.set<MooseMesh *>("mesh") = Action::_mesh.get();
160  rm_params.set<Moose::RelationshipManagerType>("rm_type") =
162 
163  // We can't attach this relationship manager early because
164  // the PeriodicBoundaries object needs to exist!
165  rm_params.set<bool>("attach_geometric_early") = false;
166 
167  if (rm_params.areAllRequiredParamsValid())
168  {
169  auto rm_obj = _factory.create<RelationshipManager>(
170  "ElementSideNeighborLayers", "periodic_bc_ghosting_" + name(), rm_params);
171 
172  if (!_app.addRelationshipManager(rm_obj))
174  }
175  else
176  mooseError("Invalid initialization of ElementSideNeighborLayers");
177  }
178 
179  if (_current_task == "add_periodic_bc")
180  {
181  NonlinearSystemBase & nl = _problem->getNonlinearSystemBase();
182  _mesh = &_problem->mesh();
183  auto displaced_problem = _problem->getDisplacedProblem();
184 
186  return;
187 
188  if (_pars.isParamValid("translation"))
189  {
190  RealVectorValue translation = getParam<RealVectorValue>("translation");
191 
192  PeriodicBoundary p(translation);
193  p.myboundary = _mesh->getBoundaryID(getParam<BoundaryName>("primary"));
194  p.pairedboundary = _mesh->getBoundaryID(getParam<BoundaryName>("secondary"));
195  setPeriodicVars(p, getParam<std::vector<VariableName>>("variable"));
196 
197  _problem->addGhostedBoundary(p.myboundary);
198  _problem->addGhostedBoundary(p.pairedboundary);
199 
200  nl.dofMap().add_periodic_boundary(p);
201  if (displaced_problem)
202  displaced_problem->nlSys().dofMap().add_periodic_boundary(p);
203  }
204  else if (getParam<std::vector<std::string>>("transform_func") != std::vector<std::string>())
205  {
206  std::vector<std::string> inv_fn_names =
207  getParam<std::vector<std::string>>("inv_transform_func");
208  std::vector<std::string> fn_names = getParam<std::vector<std::string>>("transform_func");
209 
210  // If the user provided a forward transformation, he must also provide an inverse -- we can't
211  // form the inverse of an arbitrary function automatically...
212  if (inv_fn_names == std::vector<std::string>())
213  mooseError("You must provide an inv_transform_func for FunctionPeriodicBoundary!");
214 
215  FunctionPeriodicBoundary pb(*_problem, fn_names);
216  pb.myboundary = _mesh->getBoundaryID(getParam<BoundaryName>("primary"));
217  pb.pairedboundary = _mesh->getBoundaryID(getParam<BoundaryName>("secondary"));
218  setPeriodicVars(pb, getParam<std::vector<VariableName>>("variable"));
219 
220  FunctionPeriodicBoundary ipb(*_problem, inv_fn_names);
221  ipb.myboundary =
222  _mesh->getBoundaryID(getParam<BoundaryName>("secondary")); // these are swapped
223  ipb.pairedboundary =
224  _mesh->getBoundaryID(getParam<BoundaryName>("primary")); // these are swapped
225  setPeriodicVars(ipb, getParam<std::vector<VariableName>>("variable"));
226 
227  _problem->addGhostedBoundary(ipb.myboundary);
228  _problem->addGhostedBoundary(ipb.pairedboundary);
229 
230  // Add the pair of periodic boundaries to the dof map
231  nl.dofMap().add_periodic_boundary(pb, ipb);
232  if (displaced_problem)
233  displaced_problem->nlSys().dofMap().add_periodic_boundary(pb, ipb);
234  }
235  else
236  {
237  mooseError(
238  "You have to specify either 'auto_direction', 'translation' or 'trans_func' in your "
239  "period boundary section '" +
240  _name + "'");
241  }
242  }
243 }
bool isParamValid(const std::string &name) const
Definition: Action.h:115
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, InputParameters parameters, THREAD_ID tid=0, bool print_deprecated=true)
Build an object (must be registered) - THIS METHOD IS DEPRECATED (Use create<T>()) ...
Definition: Factory.C:87
This Action adds a periodic boundary to the problem.
void setPeriodicVars(PeriodicBoundaryBase &p, const std::vector< VariableName > &var_names)
RelationshipManagerType
Main types of Relationship Managers.
Definition: MooseTypes.h:716
registerMooseAction("MooseApp", AddPeriodicBCAction, "add_periodic_bc")
const std::string & name() const
The name of the action.
Definition: Action.h:76
VectorValue< Real > RealVectorValue
Definition: Assembly.h:31
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:207
unsigned int number() const
Get variable number coming from libMesh.
bool isDistributedMesh() const
Returns the final Mesh distribution type.
Definition: MooseMesh.h:784
InputParameters getValidParams(const std::string &name)
Get valid parameters for the object.
Definition: Factory.C:67
Periodic boundary for calculation periodic BC on domains where the translation is given by functions...
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition: Action.h:224
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
Factory & _factory
The Factory associated with the MooseApp.
Definition: Action.h:186
Base class for actions.
Definition: Action.h:35
const std::set< BoundaryID > & meshBoundaryIds() const
Returns a read-only reference to the set of boundary IDs currently present in the Mesh...
Definition: MooseMesh.C:2322
bool autoTranslationBoundaries()
This function will automatically add the correct translation vectors for each requested dimension whe...
std::string _name
The name of the action.
Definition: Action.h:177
NonlinearSystemBase * nl
virtual void act() override
Method to add objects to the simulation or perform other setup tasks.
Nonlinear system to be solved.
MooseVariableFEBase & getVariable(THREAD_ID tid, const std::string &var_name)
Gets a reference to a variable of with specified name.
Definition: SystemBase.C:105
virtual DofMap & dofMap()
Gets writeable reference to the dof map.
Definition: SystemBase.C:932
bool addRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Transfers ownership of a RelationshipManager to the application for lifetime management.
Definition: MooseApp.C:1692
InputParameters _pars
Input parameters for the action.
Definition: Action.h:171
virtual unsigned int dimension() const
Returns MeshBase::mesh_dimsension(), (not MeshBase::spatial_dimension()!) of the underlying libMesh m...
Definition: MooseMesh.C:2133
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:74
const std::pair< BoundaryID, BoundaryID > * getPairedBoundaryMapping(unsigned int component)
This function attempts to return the paired boundary ids for the given component. ...
Definition: MooseMesh.C:1547
const std::string & _current_task
The current action (even though we have seperate instances for each action)
Definition: Action.h:210
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:166
AddPeriodicBCAction(InputParameters params)
void addPeriodicVariable(unsigned int var_num, BoundaryID primary, BoundaryID secondary)
For "regular orthogonal" meshes, determine if variable var_num is periodic with respect to the primar...
Definition: MooseMesh.C:1484
std::shared_ptr< MooseMesh > & _mesh
Definition: Action.h:212
bool detectOrthogonalDimRanges(Real tol=1e-6)
This routine determines whether the Mesh is a regular orthogonal mesh (i.e.
Definition: MooseMesh.C:1283
RelationshipManagers are used for describing what kinds of non-local resources are needed for an obje...
Real dimensionWidth(unsigned int component) const
Returns the width of the requested dimension.
Definition: MooseMesh.C:1460
const std::vector< VariableName > & getVariableNames() const
Definition: SystemBase.h:710
std::shared_ptr< FEProblemBase > & _problem
Convenience reference to a problem this action works on.
Definition: Action.h:216
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
MooseApp & _app
The MOOSE application this is associated with.
Definition: Action.h:183
virtual bool hasScalarVariable(const std::string &var_name) const
Definition: SystemBase.C:677
InputParameters validParams< AddPeriodicBCAction >()
InputParameters validParams< Action >()
Definition: Action.C:22
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
Definition: MooseMesh.C:1007
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.