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 "SideSetsFromAllNormalsGenerator.h" 11 : #include "Parser.h" 12 : #include "InputParameters.h" 13 : #include "CastUniquePointer.h" 14 : #include "MeshTraversingUtils.h" 15 : 16 : #include "libmesh/fe_base.h" 17 : #include "libmesh/mesh_generation.h" 18 : #include "libmesh/mesh.h" 19 : #include "libmesh/string_to_enum.h" 20 : #include "libmesh/quadrature_gauss.h" 21 : #include "libmesh/point_locator_base.h" 22 : #include "libmesh/distributed_mesh.h" 23 : #include "libmesh/elem.h" 24 : 25 : #include <typeinfo> 26 : 27 : registerMooseObject("MooseApp", SideSetsFromAllNormalsGenerator); 28 : registerMooseObjectRenamed("MooseApp", 29 : AllSideSetsByNormalsGenerator, 30 : "06/30/2027 24:00", 31 : SideSetsFromAllNormalsGenerator); 32 : 33 : InputParameters 34 6200 : SideSetsFromAllNormalsGenerator::validParams() 35 : { 36 6200 : InputParameters params = SideSetsGeneratorBase::validParams(); 37 : 38 : // This is the expected behavior of this sideset generator 39 18600 : params.setParameters("include_only_external_sides", true); 40 12400 : params.suppressParameter<bool>("include_only_external_sides"); 41 : 42 : // The normals are found from the actual orientation of sidesets, not user-specified 43 12400 : params.suppressParameter<bool>("fixed_normal"); 44 12400 : params.suppressParameter<Point>("normal"); 45 12400 : params.suppressParameter<Real>("normal_tol"); 46 12400 : params.suppressParameter<std::vector<BoundaryName>>("new_boundary"); 47 : 48 6200 : params.addClassDescription("Adds sidesets to the entire mesh based on unique normals."); 49 6200 : return params; 50 0 : } 51 : 52 39 : SideSetsFromAllNormalsGenerator::SideSetsFromAllNormalsGenerator(const InputParameters & parameters) 53 : : SideSetsGeneratorBase(parameters), 54 39 : _boundary_to_normal_map( 55 78 : declareMeshProperty<std::map<BoundaryID, RealVectorValue>>("boundary_normals")) 56 : { 57 39 : } 58 : 59 : std::unique_ptr<MeshBase> 60 39 : SideSetsFromAllNormalsGenerator::generate() 61 : { 62 39 : std::unique_ptr<MeshBase> mesh = std::move(_input); 63 39 : if (!mesh->is_replicated()) 64 0 : mooseError("SideSetsFromAllNormalsGenerator is not implemented for distributed meshes"); 65 39 : setup(*mesh); 66 : 67 : // Get the current list of boundaries so we can generate new ones that won't conflict 68 39 : _mesh_boundary_ids = mesh->get_boundary_info().get_boundary_ids(); 69 : 70 39 : _visited.clear(); 71 : 72 : // We'll need to loop over all of the elements to find ones that match this normal. 73 : // We can't rely on flood catching them all here... 74 164127 : for (const auto & elem : mesh->element_ptr_range()) 75 491868 : for (const auto side : make_range(elem->n_sides())) 76 : { 77 409824 : const std::vector<Point> & normals = _fe_face->get_normals(); 78 409824 : _fe_face->reinit(elem, side); 79 : 80 : { 81 : // See if we've seen this normal before (linear search) 82 409824 : const std::map<BoundaryID, RealVectorValue>::value_type * item = nullptr; 83 1996920 : for (const auto & id_pair : _boundary_to_normal_map) 84 1996652 : if (MeshTraversingUtils::normalsWithinTol(id_pair.second, normals[0], 1e-5)) 85 : { 86 409556 : item = &id_pair; 87 409556 : break; 88 : } 89 : 90 409824 : if (item) 91 409556 : flood(elem, normals[0], item->first, *mesh); 92 : else 93 : { 94 268 : boundary_id_type id = getNextBoundaryID(); 95 268 : _boundary_to_normal_map[id] = normals[0]; 96 268 : flood(elem, normals[0], id, *mesh); 97 : } 98 : } 99 39 : } 100 : 101 39 : finalize(); 102 : 103 39 : mesh->unset_is_prepared(); 104 78 : return dynamic_pointer_cast<MeshBase>(mesh); 105 39 : } 106 : 107 : boundary_id_type 108 268 : SideSetsFromAllNormalsGenerator::getNextBoundaryID() 109 : { 110 268 : std::set<boundary_id_type>::iterator it; 111 268 : boundary_id_type next_id = 1; 112 : 113 3138 : while ((it = _mesh_boundary_ids.find(next_id)) != _mesh_boundary_ids.end()) 114 2870 : ++next_id; 115 : 116 268 : _mesh_boundary_ids.insert(next_id); 117 : 118 268 : return next_id; 119 : }