void AddPeriodicBCAction::act() { NonlinearSystem & nl = _problem->getNonlinearSystem(); _mesh = &_problem->mesh(); if (autoTranslationBoundaries()) return; if (_pars.isParamValid("translation")) { RealVectorValue translation = getParam<RealVectorValue>("translation"); PeriodicBoundary p(translation); p.myboundary = _mesh->getBoundaryID(getParam<BoundaryName>("primary")); p.pairedboundary = _mesh->getBoundaryID(getParam<BoundaryName>("secondary")); setPeriodicVars(p, getParam<std::vector<VariableName> >("variable")); _problem->addGhostedBoundary(p.myboundary); _problem->addGhostedBoundary(p.pairedboundary); nl.dofMap().add_periodic_boundary(p); } else if (getParam<std::vector<std::string> >("transform_func") != std::vector<std::string>()) { std::vector<std::string> inv_fn_names = getParam<std::vector<std::string> >("inv_transform_func"); std::vector<std::string> fn_names = getParam<std::vector<std::string> >("transform_func"); // If the user provided a forward transformation, he must also provide an inverse -- we can't // form the inverse of an arbitrary function automatically... if (inv_fn_names == std::vector<std::string>()) mooseError("You must provide an inv_transform_func for FunctionPeriodicBoundary!"); FunctionPeriodicBoundary pb(*_problem, fn_names); pb.myboundary = _mesh->getBoundaryID(getParam<BoundaryName>("primary")); pb.pairedboundary = _mesh->getBoundaryID(getParam<BoundaryName>("secondary")); setPeriodicVars(pb, getParam<std::vector<VariableName> >("variable")); FunctionPeriodicBoundary ipb(*_problem, inv_fn_names); ipb.myboundary = _mesh->getBoundaryID(getParam<BoundaryName>("secondary")); // these are swapped ipb.pairedboundary = _mesh->getBoundaryID(getParam<BoundaryName>("primary")); // these are swapped setPeriodicVars(ipb, getParam<std::vector<VariableName> >("variable")); _problem->addGhostedBoundary(ipb.myboundary); _problem->addGhostedBoundary(ipb.pairedboundary); // Add the pair of periodic boundaries to the dof map nl.dofMap().add_periodic_boundary(pb, ipb); } else { mooseError("You have to specify either 'auto_direction', 'translation' or 'trans_func' in your period boundary section '" + _name + "'"); } }
bool AddPeriodicBCAction::autoTranslationBoundaries() { if (isParamValid("auto_direction")) { // If we are working with a parallel mesh then we're going to ghost all the boundaries everywhere because we don't know what we need... if (_mesh->isParallelMesh()) { const std::set<BoundaryID> & ids = _mesh->meshBoundaryIds(); for (std::set<BoundaryID>::const_iterator id_it = ids.begin(); id_it != ids.end(); ++id_it) _problem->addGhostedBoundary(*id_it); _problem->ghostGhostedBoundaries(); _mesh->detectOrthogonalDimRanges(); } NonlinearSystem & nl = _problem->getNonlinearSystem(); std::vector<std::string> auto_dirs = getParam<std::vector<std::string> >("auto_direction"); int dim_offset = _mesh->dimension() - 2; for (unsigned int i=0; i<auto_dirs.size(); ++i) { int component = -1; if (auto_dirs[i] == "X" || auto_dirs[i] == "x") component = 0; else if (auto_dirs[i] == "Y" || auto_dirs[i] == "y") { if (dim_offset < 0) mooseError("Cannot wrap 'Y' direction when using a 1D mesh"); component = 1; } else if (auto_dirs[i] == "Z" || auto_dirs[i] == "z") { if (dim_offset <= 0) mooseError("Cannot wrap 'Z' direction when using a 1D or 2D mesh"); component = 2; } if (component >= 0) { std::pair<BoundaryID, BoundaryID> *boundary_ids = _mesh->getPairedBoundaryMapping(component); RealVectorValue v; v(component) = _mesh->dimensionWidth(component); PeriodicBoundary p(v); if (boundary_ids == NULL) mooseError("Couldn't auto-detect a paired boundary for use with periodic boundary conditions"); p.myboundary = boundary_ids->first; p.pairedboundary = boundary_ids->second; setPeriodicVars(p, getParam<std::vector<VariableName> >("variable")); nl.dofMap().add_periodic_boundary(p); } } return true; } return false; }
bool AddPeriodicBCAction::autoTranslationBoundaries() { auto displaced_problem = _problem->getDisplacedProblem(); if (isParamValid("auto_direction")) { // If we are working with a parallel mesh then we're going to ghost all the boundaries // everywhere because we don't know what we need... if (_mesh->isDistributedMesh()) { const std::set<BoundaryID> & ids = _mesh->meshBoundaryIds(); for (const auto & bid : ids) _problem->addGhostedBoundary(bid); _problem->ghostGhostedBoundaries(); bool is_orthogonal_mesh = _mesh->detectOrthogonalDimRanges(); // If we can't detect the orthogonal dimension ranges for this // Mesh, then auto_direction periodicity isn't going to work. if (!is_orthogonal_mesh) mooseError("Could not detect orthogonal dimension ranges for DistributedMesh."); } NonlinearSystemBase & nl = _problem->getNonlinearSystemBase(); std::vector<std::string> auto_dirs = getParam<std::vector<std::string>>("auto_direction"); int dim_offset = _mesh->dimension() - 2; for (const auto & dir : auto_dirs) { int component = -1; if (dir == "X" || dir == "x") component = 0; else if (dir == "Y" || dir == "y") { if (dim_offset < 0) mooseError("Cannot wrap 'Y' direction when using a 1D mesh"); component = 1; } else if (dir == "Z" || dir == "z") { if (dim_offset <= 0) mooseError("Cannot wrap 'Z' direction when using a 1D or 2D mesh"); component = 2; } if (component >= 0) { const std::pair<BoundaryID, BoundaryID> * boundary_ids = _mesh->getPairedBoundaryMapping(component); RealVectorValue v; v(component) = _mesh->dimensionWidth(component); PeriodicBoundary p(v); if (boundary_ids == NULL) mooseError( "Couldn't auto-detect a paired boundary for use with periodic boundary conditions"); p.myboundary = boundary_ids->first; p.pairedboundary = boundary_ids->second; setPeriodicVars(p, getParam<std::vector<VariableName>>("variable")); nl.dofMap().add_periodic_boundary(p); if (displaced_problem) displaced_problem->nlSys().dofMap().add_periodic_boundary(p); } } return true; } return false; }