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 "SBMSurfaceMeshBuilder.h" 11 : #include "InputParameters.h" 12 : #include "SBMBndEdge2.h" 13 : #include "SBMBndTri3.h" 14 : #include "SBMUtils.h" 15 : 16 : // Register object 17 : registerMooseObject("ShiftedBoundaryMethodApp", SBMSurfaceMeshBuilder); 18 : 19 : InputParameters 20 102 : SBMSurfaceMeshBuilder::validParams() 21 : { 22 102 : InputParameters params = GeneralUserObject::validParams(); 23 102 : params.addClassDescription( 24 : "Constructs a KDTree and boundary elements from a pre-existing surface mesh. " 25 : "The surface mesh is specified in the Mesh block."); 26 : 27 204 : params.addRequiredParam<std::string>( 28 : "surface_mesh", 29 : "The name of the surface mesh saved via the MeshGenerator's `save_mesh_as` parameter."); 30 : 31 : /// Add a parameter for leaf_max_size for nanoflann 32 204 : params.addParam<int>( 33 : "leaf_max_size", 34 204 : 10, 35 : "Maximum number of points allowed in a leaf node of the KDTree. " 36 : "Smaller values yield deeper trees with faster queries but slower build times; " 37 : "larger values result in shallower trees with faster builds but slower queries. " 38 : "Benchmarking is recommended to find an optimal tradeoff for your use case."); 39 : 40 : /// Checking watertightness is not mandatory, but it is a good practice to ensure the mesh is valid for In-Out test. 41 204 : params.addParam<bool>( 42 : "check_watertightness", 43 204 : false, 44 : "Check if the mesh is watertight. If false, the mesh may not be suitable for In-Out tests."); 45 : 46 : /// Add a parameter to control whether to build a kd-tree or not 47 204 : params.addParam<bool>( 48 : "build_kd_tree", 49 204 : true, 50 : "Whether to build a kd-tree or not. If false, the kd-tree will not be built, " 51 : "and the mesh will be used directly for queries."); 52 : 53 102 : return params; 54 0 : } 55 : 56 51 : SBMSurfaceMeshBuilder::SBMSurfaceMeshBuilder(const InputParameters & parameters) 57 : : GeneralUserObject(parameters), 58 102 : _leaf_max_size(getParam<int>("leaf_max_size")), 59 102 : _bnd_mesh_name(getParam<std::string>("surface_mesh")), 60 102 : _check_watertightness(getParam<bool>("check_watertightness")), 61 102 : _build_kd_tree(getParam<bool>("build_kd_tree")), 62 102 : _dim_embedding_mesh(_fe_problem.mesh().dimension() /*MooseMesh*/) 63 : { 64 51 : } 65 : 66 : void 67 47 : SBMSurfaceMeshBuilder::initialSetup() 68 : { 69 47 : auto & mesh_generator_system = _app.getMeshGeneratorSystem(); 70 : 71 94 : _mesh = mesh_generator_system.getSavedMesh(_bnd_mesh_name); 72 : 73 47 : const auto expected_dim_embedding_mesh = _mesh->mesh_dimension() + 1; 74 : 75 47 : if (!_mesh->is_replicated()) 76 2 : mooseError( 77 : "The mesh is distributed. Please use a serial mesh for SBMSurfaceMeshBuilder, which is " 78 : "important for our In-Out test later."); 79 : 80 45 : if (_dim_embedding_mesh != expected_dim_embedding_mesh) 81 2 : mooseError("The original mesh dimension (", 82 2 : _dim_embedding_mesh, 83 : ") does not match the expected mesh dimension (", 84 : expected_dim_embedding_mesh, 85 : ")."); 86 : 87 43 : const std::size_t num_elems = _mesh->n_elem(); 88 : 89 43 : _centroids.resize(num_elems); 90 43 : _boundary_elements.resize(num_elems); 91 : 92 : int i = 0; 93 576 : for (auto elem_it = _mesh->active_elements_begin(); elem_it != _mesh->active_elements_end(); 94 245 : ++elem_it) 95 : { 96 247 : const Elem * elem = *elem_it; 97 : 98 247 : const auto centroid = elem->vertex_average(); 99 247 : if (_build_kd_tree) 100 219 : _centroids[i] = centroid; 101 : 102 247 : if (elem->type() == EDGE2) 103 125 : _boundary_elements[i] = std::make_unique<SBMBndEdge2>(elem); 104 122 : else if (elem->type() == TRI3) 105 120 : _boundary_elements[i] = std::make_unique<SBMBndTri3>(elem); 106 : else 107 2 : mooseError("Unsupported element type in SBMSurfaceMeshBuilder::initialSetup()"); 108 : 109 245 : ++i; 110 : } 111 : 112 41 : if (_build_kd_tree) 113 68 : _kd_tree = std::make_unique<KDTree>(_centroids, _leaf_max_size); 114 : 115 41 : if (_check_watertightness) 116 : { 117 9 : bool watertight = checkWatertightness(); 118 9 : if (!watertight) 119 4 : mooseInfo("The mesh is not watertight. It may not be suitable for In-Out tests."); 120 : else 121 5 : mooseInfo("The mesh is watertight. It is suitable for In-Out tests."); 122 : } 123 41 : } 124 : 125 : bool 126 9 : SBMSurfaceMeshBuilder::checkWatertightness() const 127 : { 128 9 : return SBMUtils::checkWatertightnessFromRawElems(std::vector<const Elem *>( 129 27 : _mesh->active_element_ptr_range().begin(), _mesh->active_element_ptr_range().end())); 130 : } 131 : 132 : KDTree & 133 36 : SBMSurfaceMeshBuilder::getKDTree() const 134 : { 135 : mooseAssert(_kd_tree, "KDTree not built; callers must guard with hasKDTree() first."); 136 36 : return *_kd_tree; 137 : } 138 : 139 : const std::vector<std::unique_ptr<SBMBndElementBase>> & 140 36 : SBMSurfaceMeshBuilder::getBoundaryElements() const 141 : { 142 36 : return _boundary_elements; 143 : } 144 : 145 : const std::vector<Point> & 146 6 : SBMSurfaceMeshBuilder::getCentroids() const 147 : { 148 6 : return _centroids; 149 : }