$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 #ifndef LIBMESH_SPARSITY_PATTERN_H 00020 #define LIBMESH_SPARSITY_PATTERN_H 00021 00022 // Local Includes 00023 #include "libmesh/elem_range.h" 00024 #include "libmesh/threads_allocators.h" 00025 #include "libmesh/parallel_object.h" 00026 00027 // C++ includes 00028 #include <vector> 00029 00030 namespace libMesh 00031 { 00032 00033 // Forward declaractions 00034 class MeshBase; 00035 class DofMap; 00036 class CouplingMatrix; 00037 00038 // ------------------------------------------------------------ 00039 // Sparsity Pattern 00040 00047 namespace SparsityPattern // use a namespace so member classes can be forward-declared. 00048 { 00049 typedef std::vector<dof_id_type, Threads::scalable_allocator<dof_id_type> > Row; 00050 class Graph : public std::vector<Row> {}; 00051 00052 class NonlocalGraph : public std::map<dof_id_type, Row> {}; 00053 00063 template<typename BidirectionalIterator> 00064 static void sort_row (const BidirectionalIterator begin, 00065 BidirectionalIterator middle, 00066 const BidirectionalIterator end); 00067 00079 class Build : public ParallelObject 00080 { 00081 private: 00082 const MeshBase &mesh; 00083 const DofMap &dof_map; 00084 const CouplingMatrix *dof_coupling; 00085 const bool implicit_neighbor_dofs; 00086 const bool need_full_sparsity_pattern; 00087 00088 public: 00089 00090 SparsityPattern::Graph sparsity_pattern; 00091 SparsityPattern::NonlocalGraph nonlocal_pattern; 00092 00093 std::vector<dof_id_type> n_nz; 00094 std::vector<dof_id_type> n_oz; 00095 00096 Build (const MeshBase &mesh_in, 00097 const DofMap &dof_map_in, 00098 const CouplingMatrix *dof_coupling_in, 00099 const bool implicit_neighbor_dofs_in, 00100 const bool need_full_sparsity_pattern_in); 00101 00102 Build (Build &other, Threads::split); 00103 00104 void operator()(const ConstElemRange &range); 00105 00106 void join (const Build &other); 00107 00108 void parallel_sync (); 00109 }; 00110 00111 #if defined(__GNUC__) && (__GNUC__ < 4) && !defined(__INTEL_COMPILER) 00112 00117 void _dummy_function(void); 00118 #endif 00119 00120 } 00121 00122 00123 00124 // ------------------------------------------------------------ 00125 // SparsityPattern inline member functions 00126 template<typename BidirectionalIterator> 00127 inline 00128 void SparsityPattern::sort_row (const BidirectionalIterator begin, 00129 BidirectionalIterator middle, 00130 const BidirectionalIterator end) 00131 { 00132 if ((begin == middle) || (middle == end)) return; 00133 00134 libmesh_assert_greater (std::distance (begin, middle), 0); 00135 libmesh_assert_greater (std::distance (middle, end), 0); 00136 libmesh_assert (std::unique (begin, middle) == middle); 00137 libmesh_assert (std::unique (middle, end) == end); 00138 00139 while (middle != end) 00140 { 00141 BidirectionalIterator 00142 b = middle, 00143 a = b-1; 00144 00145 // Bubble-sort the middle value downward 00146 while (!(*a < *b)) // *a & *b are less-than comparable, so use < 00147 { 00148 std::swap (*a, *b); 00149 00150 #if defined(__GNUC__) && (__GNUC__ < 4) && !defined(__INTEL_COMPILER) 00151 /* Prohibit optimization at this point since gcc 3.3.5 seems 00152 to have a bug. */ 00153 SparsityPattern::_dummy_function(); 00154 #endif 00155 00156 if (a == begin) break; 00157 00158 b=a; 00159 --a; 00160 } 00161 00162 ++middle; 00163 } 00164 00165 // Assure the algorithm worked if we are in DEBUG mode 00166 #ifdef DEBUG 00167 { 00168 // SGI STL extension! 00169 // libmesh_assert (std::is_sorted(begin,end)); 00170 00171 BidirectionalIterator 00172 prev = begin, 00173 first = begin; 00174 00175 for (++first; first != end; prev=first, ++first) 00176 if (*first < *prev) 00177 libmesh_assert(false); 00178 } 00179 #endif 00180 00181 // Make sure the two ranges did not contain any common elements 00182 libmesh_assert (std::unique (begin, end) == end); 00183 } 00184 00185 } // namespace libMesh 00186 00187 #endif // LIBMESH_SPARSITY_PATTERN_H