Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 : 4 : // This library is free software; you can redistribute it and/or 5 : // modify it under the terms of the GNU Lesser General Public 6 : // License as published by the Free Software Foundation; either 7 : // version 2.1 of the License, or (at your option) any later version. 8 : 9 : // This library is distributed in the hope that it will be useful, 10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 : // Lesser General Public License for more details. 13 : 14 : // You should have received a copy of the GNU Lesser General Public 15 : // License along with this library; if not, write to the Free Software 16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 : 18 : 19 : 20 : // C++ includes 21 : 22 : 23 : // Local includes 24 : #include "libmesh/system_subset_by_subdomain.h" 25 : #include "libmesh/system.h" 26 : #include "libmesh/dof_map.h" 27 : #include "libmesh/parallel.h" 28 : #include "libmesh/elem.h" 29 : 30 : namespace libMesh 31 : { 32 : // ------------------------------------------------------------ 33 : // SubdomainSelection implementation 34 198 : SystemSubsetBySubdomain::SubdomainSelection::SubdomainSelection () = default; 35 198 : SystemSubsetBySubdomain::SubdomainSelection::~SubdomainSelection () = default; 36 : 37 210 : SystemSubsetBySubdomain::SubdomainSelectionByList:: 38 210 : SubdomainSelectionByList (const std::set<subdomain_id_type> & list): 39 210 : _list(list) 40 : { 41 210 : } 42 : 43 : bool 44 102421 : SystemSubsetBySubdomain::SubdomainSelectionByList:: 45 : operator()(const subdomain_id_type & subdomain_id)const 46 : { 47 102421 : return _list.count(subdomain_id); // _list is actually a std::set 48 : } 49 : 50 : // ------------------------------------------------------------ 51 : // SystemSubsetBySubdomain implementation 52 : 53 210 : SystemSubsetBySubdomain:: 54 : SystemSubsetBySubdomain (const System & system, 55 : const SubdomainSelection & subdomain_selection, 56 210 : const std::set<unsigned int> * const var_nums): 57 : SystemSubset(system), 58 : ParallelObject(system), 59 : _var_nums(), 60 210 : _dof_ids() 61 : { 62 210 : this->set_var_nums(var_nums); 63 210 : this->init(subdomain_selection); 64 210 : } 65 : 66 0 : SystemSubsetBySubdomain:: 67 : SystemSubsetBySubdomain (const System & system, 68 : const std::set<subdomain_id_type> & subdomain_ids, 69 0 : const std::set<unsigned int> * const var_nums): 70 : SystemSubset(system), 71 : ParallelObject(system), 72 : _var_nums(), 73 0 : _dof_ids() 74 : { 75 0 : this->set_var_nums(var_nums); 76 0 : this->init(subdomain_ids); 77 0 : } 78 : 79 396 : SystemSubsetBySubdomain::~SystemSubsetBySubdomain () = default; 80 : 81 : const std::vector<unsigned int> & 82 210 : SystemSubsetBySubdomain::dof_ids() const 83 : { 84 210 : return _dof_ids; 85 : } 86 : 87 : void 88 210 : SystemSubsetBySubdomain:: 89 : set_var_nums (const std::set<unsigned int> * const var_nums) 90 : { 91 6 : _var_nums.clear(); 92 : 93 210 : if (var_nums != nullptr) 94 0 : _var_nums = *var_nums; 95 : 96 : else 97 420 : for (auto i : make_range(_system.n_vars())) 98 204 : _var_nums.insert(i); 99 210 : } 100 : 101 : void 102 210 : SystemSubsetBySubdomain:: 103 : init (const SubdomainSelection & subdomain_selection) 104 : { 105 210 : _dof_ids.clear(); 106 : 107 228 : std::vector<std::vector<dof_id_type>> dof_ids_per_processor(this->n_processors()); 108 : 109 210 : const DofMap & dof_map = _system.get_dof_map(); 110 12 : std::vector<dof_id_type> dof_indices; 111 : 112 12 : const MeshBase & mesh = _system.get_mesh(); 113 186634 : for (const auto & elem : mesh.active_local_element_ptr_range()) 114 111732 : if (subdomain_selection(elem->subdomain_id())) 115 : { 116 79046 : for (const auto & var_num : _var_nums) 117 : { 118 39523 : dof_map.dof_indices (elem, dof_indices, var_num); 119 325831 : for (const auto & dof : dof_indices) 120 2108268 : for (auto proc : make_range(this->n_processors())) 121 1874016 : if ((dof>=dof_map.first_dof(proc)) && (dof<dof_map.end_dof(proc))) 122 312336 : dof_ids_per_processor[proc].push_back(dof); 123 : } 124 198 : } 125 : 126 : /* Distribute information among processors. */ 127 228 : std::vector<Parallel::Request> request_per_processor(this->n_processors()); 128 2286 : for (auto proc : make_range(this->n_processors())) 129 2088 : if (proc!=this->processor_id()) 130 1872 : this->comm().send(proc,dof_ids_per_processor[proc],request_per_processor[proc]); 131 2286 : for (auto proc : make_range(this->n_processors())) 132 : { 133 12 : std::vector<dof_id_type> received_dofs; 134 2088 : if (proc==this->processor_id()) 135 216 : received_dofs = dof_ids_per_processor[proc]; 136 : else 137 1866 : this->comm().receive(proc,received_dofs); 138 2076 : _dof_ids.insert(_dof_ids.end(), received_dofs.begin(), received_dofs.end()); 139 : } 140 : 141 : /* Sort and unique the vector (using the same mechanism as in \p 142 : DofMap::prepare_send_list()). */ 143 210 : std::sort(_dof_ids.begin(), _dof_ids.end()); 144 210 : std::vector<unsigned int>::iterator new_end = std::unique (_dof_ids.begin(), _dof_ids.end()); 145 408 : std::vector<unsigned int> (_dof_ids.begin(), new_end).swap (_dof_ids); 146 : 147 : /* Wait for sends to be complete. */ 148 2286 : for (auto proc : make_range(this->n_processors())) 149 : { 150 2088 : if (proc!=this->processor_id()) 151 : { 152 1872 : request_per_processor[proc].wait(); 153 : } 154 : } 155 408 : } 156 : 157 : void 158 0 : SystemSubsetBySubdomain:: 159 : init (const std::set<subdomain_id_type> & subdomain_ids) 160 : { 161 0 : SubdomainSelectionByList selection(subdomain_ids); 162 0 : this->init(selection); 163 0 : } 164 : 165 : } // namespace libMesh