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 "SideSetsFromPointsGenerator.h" 11 : #include "Parser.h" 12 : #include "InputParameters.h" 13 : #include "MooseMeshUtils.h" 14 : #include "CastUniquePointer.h" 15 : 16 : #include "libmesh/mesh.h" 17 : #include "libmesh/mesh_generation.h" 18 : #include "libmesh/mesh_serializer.h" 19 : #include "libmesh/string_to_enum.h" 20 : #include "libmesh/quadrature_gauss.h" 21 : #include "libmesh/point_locator_base.h" 22 : #include "libmesh/enum_point_locator_type.h" 23 : #include "libmesh/distributed_mesh.h" 24 : #include "libmesh/elem.h" 25 : #include "libmesh/fe_base.h" 26 : #include "libmesh/mesh_tools.h" 27 : 28 : #include <typeinfo> 29 : 30 : registerMooseObject("MooseApp", SideSetsFromPointsGenerator); 31 : 32 : InputParameters 33 14309 : SideSetsFromPointsGenerator::validParams() 34 : { 35 14309 : InputParameters params = SideSetsGeneratorBase::validParams(); 36 : 37 14309 : params.addClassDescription("Adds a new sideset starting at the specified point containing all " 38 : "connected element faces with the same normal."); 39 14309 : params.addRequiredParam<std::vector<Point>>( 40 : "points", "A list of points from which to start painting sidesets"); 41 : 42 14309 : params.suppressParameter<Point>("normal"); 43 14309 : params.suppressParameter<Real>("normal_tol"); 44 : 45 : // It doesn't make sense to allow internal sides for this side set generator. 46 14309 : params.setParameters("include_only_external_sides", true); 47 14309 : params.suppressParameter<bool>("include_only_external_sides"); 48 : 49 14309 : return params; 50 0 : } 51 : 52 22 : SideSetsFromPointsGenerator::SideSetsFromPointsGenerator(const InputParameters & parameters) 53 22 : : SideSetsGeneratorBase(parameters), _points(getParam<std::vector<Point>>("points")) 54 : { 55 22 : if (_points.size() != _boundary_names.size()) 56 0 : mooseError("point list and boundary list are not the same length"); 57 22 : _using_normal = true; 58 22 : } 59 : 60 : std::unique_ptr<MeshBase> 61 21 : SideSetsFromPointsGenerator::generate() 62 : { 63 21 : std::unique_ptr<MeshBase> mesh = std::move(_input); 64 : 65 : // Our flood fill doesn't do any communication, so it requires a 66 : // serialized mesh 67 21 : libMesh::MeshSerializer serial(*mesh); 68 : 69 : // Get the BoundaryIDs from the mesh 70 : std::vector<BoundaryID> boundary_ids = 71 21 : MooseMeshUtils::getBoundaryIDs(*mesh, _boundary_names, true); 72 : 73 21 : setup(*mesh); 74 : 75 21 : _visited.clear(); 76 : 77 : std::unique_ptr<libMesh::PointLocatorBase> pl = 78 21 : libMesh::PointLocatorBase::build(libMesh::TREE, *mesh); 79 : 80 81 : for (const auto i : index_range(boundary_ids)) 81 : { 82 64 : std::set<const Elem *> candidate_elements; 83 64 : (*pl)(_points[i], candidate_elements); 84 : 85 64 : const Elem * elem_to_flood = nullptr; 86 64 : Point normal_to_flood; 87 : 88 168 : for (const Elem * elem : candidate_elements) 89 592 : for (const auto side : make_range(elem->n_sides())) 90 : { 91 488 : if (elem->neighbor_ptr(side)) 92 376 : continue; 93 : 94 : // See if this point is on this side 95 112 : std::unique_ptr<const Elem> elem_side = elem->side_ptr(side); 96 : 97 112 : if (elem_side->contains_point(_points[i])) 98 : { 99 : // This is a good side to paint our sideset with. 100 : // Get the normal. 101 112 : const std::vector<Point> & normals = _fe_face->get_normals(); 102 112 : _fe_face->reinit(elem, side); 103 : 104 : // If we *already* found a good but different side to paint 105 : // our sideset with, we've got an ambiguity here. 106 156 : if (elem_to_flood && (!normalsWithinTol(normal_to_flood, normals[0], _normal_tol) || 107 44 : elem_to_flood->which_neighbor_am_i(elem) == libMesh::invalid_uint)) 108 4 : mooseError("Two ambiguous potential sideset sources found for boundary `", 109 4 : _boundary_names[i], 110 : "' at ", 111 4 : _points[i], 112 : ":\nElement ", 113 4 : elem_to_flood->id(), 114 : " normal ", 115 : normal_to_flood, 116 : " and\n", 117 : ":\nElement ", 118 4 : elem->id(), 119 : " normal ", 120 4 : normals[0]); 121 : 122 108 : elem_to_flood = elem; 123 108 : normal_to_flood = normals[0]; 124 : // Don't just flood here; keep looking for possible ambiguity 125 : } 126 108 : } 127 : 128 60 : flood(elem_to_flood, normal_to_flood, boundary_ids[i], *mesh); 129 60 : } 130 : 131 : #ifdef DEBUG 132 : MeshTools::libmesh_assert_valid_boundary_ids(*mesh); 133 : #endif 134 : 135 17 : finalize(); 136 : 137 77 : for (const auto i : index_range(boundary_ids)) 138 60 : mesh->get_boundary_info().sideset_name(boundary_ids[i]) = _boundary_names[i]; 139 : 140 17 : mesh->set_isnt_prepared(); 141 34 : return dynamic_pointer_cast<MeshBase>(mesh); 142 17 : }