$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 // C++ Includes ----------------------------------- 00021 00022 // Local Includes ----------------------------------- 00023 #include "libmesh/libmesh_config.h" 00024 #include "libmesh/mesh_base.h" 00025 #include "libmesh/sfc_partitioner.h" 00026 #include "libmesh/libmesh_logging.h" 00027 #include "libmesh/elem.h" 00028 00029 #ifdef LIBMESH_HAVE_SFCURVES 00030 namespace Sfc { 00031 extern "C" { 00032 # include "sfcurves.h" 00033 } 00034 } 00035 #else 00036 # include "libmesh/linear_partitioner.h" 00037 #endif 00038 00039 namespace libMesh 00040 { 00041 00042 00043 // ------------------------------------------------------------ 00044 // SFCPartitioner implementation 00045 void SFCPartitioner::_do_partition (MeshBase& mesh, 00046 const unsigned int n) 00047 { 00048 00049 libmesh_assert_greater (n, 0); 00050 00051 // Check for an easy return 00052 if (n == 1) 00053 { 00054 this->single_partition (mesh); 00055 return; 00056 } 00057 00058 // What to do if the sfcurves library IS NOT present 00059 #ifndef LIBMESH_HAVE_SFCURVES 00060 00061 libmesh_here(); 00062 libMesh::err << "ERROR: The library has been built without" << std::endl 00063 << "Space Filling Curve support. Using a linear" << std::endl 00064 << "partitioner instead!" << std::endl; 00065 00066 LinearPartitioner lp; 00067 00068 lp.partition (mesh, n); 00069 00070 // What to do if the sfcurves library IS present 00071 #else 00072 00073 START_LOG("sfc_partition()", "SFCPartitioner"); 00074 00075 const dof_id_type n_active_elem = mesh.n_active_elem(); 00076 const dof_id_type n_elem = mesh.n_elem(); 00077 00078 // the forward_map maps the active element id 00079 // into a contiguous block of indices 00080 std::vector<dof_id_type> 00081 forward_map (n_elem, DofObject::invalid_id); 00082 00083 // the reverse_map maps the contiguous ids back 00084 // to active elements 00085 std::vector<Elem*> reverse_map (n_active_elem, NULL); 00086 00087 int size = static_cast<int>(n_active_elem); 00088 std::vector<double> x (size); 00089 std::vector<double> y (size); 00090 std::vector<double> z (size); 00091 std::vector<int> table (size); 00092 00093 00094 // We need to map the active element ids into a 00095 // contiguous range. 00096 { 00097 // active_elem_iterator elem_it (mesh.elements_begin()); 00098 // const active_elem_iterator elem_end(mesh.elements_end()); 00099 00100 MeshBase::element_iterator elem_it = mesh.active_elements_begin(); 00101 const MeshBase::element_iterator elem_end = mesh.active_elements_end(); 00102 00103 dof_id_type el_num = 0; 00104 00105 for (; elem_it != elem_end; ++elem_it) 00106 { 00107 libmesh_assert_less ((*elem_it)->id(), forward_map.size()); 00108 libmesh_assert_less (el_num, reverse_map.size()); 00109 00110 forward_map[(*elem_it)->id()] = el_num; 00111 reverse_map[el_num] = *elem_it; 00112 el_num++; 00113 } 00114 libmesh_assert_equal_to (el_num, n_active_elem); 00115 } 00116 00117 00118 // Get the centroid for each active element 00119 { 00120 // const_active_elem_iterator elem_it (mesh.const_elements_begin()); 00121 // const const_active_elem_iterator elem_end(mesh.const_elements_end()); 00122 00123 MeshBase::element_iterator elem_it = mesh.active_elements_begin(); 00124 const MeshBase::element_iterator elem_end = mesh.active_elements_end(); 00125 00126 for (; elem_it != elem_end; ++elem_it) 00127 { 00128 const Elem* elem = *elem_it; 00129 00130 libmesh_assert_less (elem->id(), forward_map.size()); 00131 00132 const Point p = elem->centroid(); 00133 00134 x[forward_map[elem->id()]] = p(0); 00135 y[forward_map[elem->id()]] = p(1); 00136 z[forward_map[elem->id()]] = p(2); 00137 } 00138 } 00139 00140 // build the space-filling curve 00141 if (_sfc_type == "Hilbert") 00142 Sfc::hilbert (&x[0], &y[0], &z[0], &size, &table[0]); 00143 00144 else if (_sfc_type == "Morton") 00145 Sfc::morton (&x[0], &y[0], &z[0], &size, &table[0]); 00146 00147 else 00148 { 00149 libmesh_here(); 00150 libMesh::err << "ERROR: Unknown type: " << _sfc_type << std::endl 00151 << " Valid types are" << std::endl 00152 << " \"Hilbert\"" << std::endl 00153 << " \"Morton\"" << std::endl 00154 << " " << std::endl 00155 << "Proceeding with a Hilbert curve." << std::endl; 00156 00157 Sfc::hilbert (&x[0], &y[0], &z[0], &size, &table[0]); 00158 } 00159 00160 00161 // Assign the partitioning to the active elements 00162 { 00163 // { 00164 // std::ofstream out ("sfc.dat"); 00165 // out << "variables=x,y,z" << std::endl; 00166 // out << "zone f=point" << std::endl; 00167 00168 // for (unsigned int i=0; i<n_active_elem; i++) 00169 // out << x[i] << " " 00170 // << y[i] << " " 00171 // << z[i] << std::endl; 00172 // } 00173 00174 const dof_id_type blksize = (n_active_elem+n-1)/n; 00175 00176 for (dof_id_type i=0; i<n_active_elem; i++) 00177 { 00178 libmesh_assert_less (static_cast<unsigned int>(table[i]-1), reverse_map.size()); 00179 00180 Elem* elem = reverse_map[table[i]-1]; 00181 00182 elem->processor_id() = cast_int<processor_id_type> 00183 (i/blksize); 00184 } 00185 } 00186 00187 STOP_LOG("sfc_partition()", "SFCPartitioner"); 00188 00189 #endif 00190 00191 } 00192 00193 } // namespace libMesh