Line data Source code
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 "SideSetsFromNormalsGenerator.h" 11 : #include "Parser.h" 12 : #include "InputParameters.h" 13 : #include "MeshTraversingUtils.h" 14 : #include "MooseMeshUtils.h" 15 : #include "CastUniquePointer.h" 16 : #include "MooseApp.h" 17 : #include "MeshGeneratorSystem.h" 18 : 19 : #include "libmesh/mesh_generation.h" 20 : #include "libmesh/mesh.h" 21 : #include "libmesh/string_to_enum.h" 22 : #include "libmesh/quadrature_gauss.h" 23 : #include "libmesh/point_locator_base.h" 24 : #include "libmesh/distributed_mesh.h" 25 : #include "libmesh/elem.h" 26 : #include "libmesh/fe_base.h" 27 : 28 : #include <typeinfo> 29 : 30 : registerMooseObject("MooseApp", SideSetsFromNormalsGenerator); 31 : 32 : InputParameters 33 3155 : SideSetsFromNormalsGenerator::validParams() 34 : { 35 3155 : InputParameters params = SideSetsGeneratorBase::validParams(); 36 : 37 6310 : params.addClassDescription( 38 : "Adds a new named sideset to the mesh for all faces matching the specified normal."); 39 9465 : params.addRequiredParam<std::vector<Point>>( 40 : "normals", "A list of normals for which to start painting sidesets"); 41 : 42 : // We want to use a different normal_tol for this generator than from the base class to preserve 43 : // old behavior. 44 9465 : params.setParameters("normal_tol", 1e-5); 45 : 46 : // We are using 'normals' instead 47 3155 : params.suppressParameter<Point>("normal"); 48 : 49 : // It doesn't make sense to allow internal sides for this side set generator. 50 9465 : params.setParameters("include_only_external_sides", true); 51 3155 : params.suppressParameter<bool>("include_only_external_sides"); 52 : 53 3155 : return params; 54 0 : } 55 : 56 47 : SideSetsFromNormalsGenerator::SideSetsFromNormalsGenerator(const InputParameters & parameters) 57 : : SideSetsGeneratorBase(parameters), 58 47 : _normals(getParam<std::vector<Point>>("normals")), 59 47 : _boundary_to_normal_map( 60 141 : declareMeshProperty<std::map<BoundaryID, RealVectorValue>>("boundary_normals")) 61 : { 62 : // Get the BoundaryIDs from the mesh 63 47 : if (_normals.size() != _boundary_names.size()) 64 0 : mooseError("normal list and boundary list are not the same length"); 65 : 66 : // Make sure that the normals are normalized 67 155 : for (auto & normal : _normals) 68 : { 69 108 : if (normal.norm() < 1e-5) 70 0 : mooseError("Normal is zero"); 71 108 : normal /= normal.norm(); 72 : } 73 : 74 47 : _using_normal = true; 75 47 : } 76 : 77 : std::unique_ptr<MeshBase> 78 46 : SideSetsFromNormalsGenerator::generate() 79 : { 80 46 : std::unique_ptr<MeshBase> mesh = std::move(_input); 81 46 : if (!_fixed_normal && !mesh->is_replicated()) 82 0 : mooseError("SideSetsFromNormalsGenerator is not implemented for distributed meshes when " 83 : "fixed_normal = false"); 84 : 85 : std::vector<BoundaryID> boundary_ids = 86 46 : MooseMeshUtils::getBoundaryIDs(*mesh, _boundary_names, true); 87 : 88 46 : setup(*mesh); 89 : 90 46 : _visited.clear(); 91 : 92 : // Request to compute normal vectors 93 46 : const std::vector<Point> & face_normals = _fe_face->get_normals(); 94 : 95 : // We'll need to loop over all of the elements to find ones that match this normal. 96 : // We can't rely on flood catching them all here... 97 70222 : for (const auto & elem : mesh->element_ptr_range()) 98 226164 : for (const auto side : make_range(elem->n_sides())) 99 : { 100 191076 : if (elem->neighbor_ptr(side)) 101 174500 : continue; 102 : 103 16576 : _fe_face->reinit(elem, side); 104 : 105 : // We'll just use the normal of the first qp 106 16576 : const Point & face_normal = face_normals[0]; 107 : 108 56392 : for (const auto i : make_range(boundary_ids.size())) 109 : { 110 39816 : if (MeshTraversingUtils::normalsWithinTol(_normals[i], face_normal, _normal_tol)) 111 5886 : flood(elem, _normals[i], boundary_ids[i], *mesh); 112 : } 113 46 : } 114 : 115 46 : finalize(); 116 : 117 46 : BoundaryInfo & boundary_info = mesh->get_boundary_info(); 118 152 : for (const auto i : make_range(boundary_ids.size())) 119 : { 120 106 : boundary_info.sideset_name(boundary_ids[i]) = _boundary_names[i]; 121 106 : _boundary_to_normal_map[boundary_ids[i]] = _normals[i]; 122 : } 123 : 124 46 : mesh->unset_is_prepared(); 125 92 : return dynamic_pointer_cast<MeshBase>(mesh); 126 46 : }