Plugins
cr_reorder.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014: G-CSC, Goethe University Frankfurt
3  * Author: Christian Wehner
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef __H__UG__PLUGINS__NAVIER_STOKES__INCOMPRESSIBLE__FVCR__CR_REORDER__
34 #define __H__UG__PLUGINS__NAVIER_STOKES__INCOMPRESSIBLE__FVCR__CR_REORDER__
35 
36 #include <vector>
39 #include <boost/graph/adjacency_list.hpp>
41 
42 namespace ug{
43 
49 struct CompareDeg {
51  CompareDeg(const std::vector<size_t>& vInfo) : m_degree(vInfo) {}
52 
54  bool operator() (size_t i,size_t j)
55  {
56  return (m_degree[i] < m_degree[j]);
57  }
58 
59 private:
61  const std::vector<size_t>& m_degree;
62 };
63 
64 void computeDegree(std::vector<size_t>& degree,std::vector<std::vector<size_t> >& vvConnections,size_t minpind);
65 
66 // compute adjacency graph on Crouzeix-Raviart-elements
67 template <typename TElem, typename TGridFunction>
68 void cr_get_connections(std::vector<std::vector<size_t> >& vvConnection,size_t& minpind, DoFDistribution& dd,TGridFunction& u){
70  typedef typename TGridFunction::domain_type domain_type;
71 
73  static const int dim = domain_type::dim;
74 
75  typename DoFDistribution::traits<TElem>::const_iterator iter, iterBegin, iterEnd;
76  LocalIndices ind;
77 
78  size_t num_dd_ind = dd.num_indices();
79 
80  // clear neighbors and resize
81  vvConnection.clear();
82  vvConnection.resize(num_dd_ind);
83 
84  minpind=num_dd_ind;
85 
86  for (int si=0;si<u.num_subsets();si++){
87  iterBegin = dd.begin<TElem>(si);
88  iterEnd = dd.end<TElem>(si);
89  // check if at least one element exist
90  if(iterBegin == iterEnd) continue;
91  // Loop over all elements
92  for(iter = iterBegin; iter != iterEnd; ++iter)
93  {
94  // get Element
95  TElem* elem = *iter;
96  // get global indices
97  dd.indices(elem, ind, false);
98  size_t num_sides = elem->num_sides();
99  size_t num_ind = num_sides * dim + 1;
100  std::vector<size_t> globind(num_ind);
101  // velocity component indices
102  for (size_t side=0;side<num_sides;side++)
103  for (int d=0;d<dim;d++)
104  globind[dim*side+d]=ind.index(d,side);
105  // pressure component index
106  size_t pind = ind.index(dim,0);
107  globind[num_ind-1]=pind;
108  if (pind<minpind) minpind=pind;
109  // add couplings to adjacency graph
110  std::vector<size_t>::iterator it;
111  for (size_t i=0;i<num_ind;i++){
112  size_t iIndex = globind[i];
113  for (size_t j=0;j<num_ind;j++){
114  size_t jIndex = globind[j];
115  // add connection (iIndex->jIndex)
116  it = find(vvConnection[iIndex].begin(), vvConnection[iIndex].end(), jIndex);
117  if(it == vvConnection[iIndex].end()) vvConnection[iIndex].push_back(jIndex);
118  // add the opposite direction (adjInd -> index)
119  it = find(vvConnection[jIndex].begin(), vvConnection[jIndex].end(), iIndex);
120  if(it == vvConnection[jIndex].end()) vvConnection[jIndex].push_back(iIndex);
121  }
122  }
123  }
124  std::vector<size_t> degree;
125  computeDegree(degree,vvConnection,minpind);
126  // Sort neighbours by degreee
127  CompareDeg myCompDegree(degree);
128  for (size_t i=0;i<vvConnection.size();i++){
129  std::sort(vvConnection[i].begin(),vvConnection[i].end(),myCompDegree);
130  };
131  }
132 }
133 
134 // extract p graph from connections, two p nodes are defined adjacent if they share a common velocity neighbour
135 template <class TGraph>
136 void extractPGraph(TGraph& G,std::vector<std::vector<size_t> >& vvConnection,size_t pmin,size_t dim,bool directed){
137  for (size_t i=0;i<pmin;i=i+dim){
138  size_t s=vvConnection[i].size();
139  int ind1 = vvConnection[i][s-2]-pmin;
140  if (ind1<0) continue;
141  int ind2 = vvConnection[i][s-1]-pmin;
142  boost::add_edge(ind1,ind2,G);
143  if (directed==true) boost::add_edge(ind2,ind1,G);
144  }
145 }
146 
147 // extract v graph from connections
148 template <class TGraph>
149 void extractVGraph(TGraph& G,std::vector<std::vector<size_t> >& vvConnection,size_t pmin,size_t dim,bool directed){
150  for (size_t i=0;i<pmin;i=i+dim){
151  size_t ind1 = (size_t)round((number)i/dim);
152  size_t s = vvConnection[i].size();
153  for (size_t j=0;j<s-1;j=j+2){
154  size_t ind2 = (size_t)round((number)vvConnection[i][j]/dim);
155  if (dim*ind2>=pmin) break;
156  if (ind1==ind2) continue;
157  boost::add_edge(ind1,ind2,G);
158  if (directed==true) boost::add_edge(ind2,ind1,G);
159  }
160  }
161 }
162 
163 void CRCuthillMcKee(std::vector<size_t>& newIndex,std::vector<std::vector<size_t> >& vvConnection,size_t dim,
164  size_t minpind,bool bReverse,bool bseparate,bool orderp,bool orderv);
165 
167 template <typename TDomain,typename TGridFunction>
168 void CROrderCuthillMcKee(ApproximationSpace<TDomain>& approxSpace,TGridFunction& u,
169  bool bReverse,bool bseparate,bool orderp,bool orderv)
170 {
172  typedef typename TGridFunction::domain_type domain_type;
173 
175  static const int dim = domain_type::dim;
176 
178  typedef typename TGridFunction::template dim_traits<dim>::grid_base_object elem_type;
179 
180  std::vector<std::vector<size_t> > vvConnection;
181  size_t minpind;
182 
183  for (int si=0;si<u.num_subsets();++si){
184  if (u.num_fct(si)<2){
185  if (u.num_fct(si)!=dim+1){
186  UG_THROW("Wrong number of components in approximation space. Needed " << dim+1 << ", given " << u.num_fct(si) << ".\n");
187  }
188  }
189  for (int d=0;d<dim;d++){
190  if (u.local_finite_element_id(d) != LFEID(LFEID::CROUZEIX_RAVIART, dim, 1)){
191  UG_THROW("Component " << d << " in approximation space must be of Crouzeix-Raviart type.");
192  }
193  }
194  if (u.local_finite_element_id(dim) != LFEID(LFEID::PIECEWISE_CONSTANT, dim, 0)){
195  UG_THROW("Component dim in approximation space must be of piecewise constant type.");
196  }
197  }
198 
199  std::vector<SmartPtr<DoFDistribution> > vDD = approxSpace.dof_distributions();
200 
201  // order levels
202  for(size_t i = 0; i < vDD.size(); ++i){
203  std::vector<size_t> newIndex;
204  cr_get_connections<elem_type,TGridFunction>(vvConnection,minpind,*vDD[i],u);
205  CRCuthillMcKee(newIndex,vvConnection,dim,minpind,bReverse,bseparate,orderp,orderv);
206  vDD[i]->permute_indices(newIndex);
207  }
208 }
209 
210 void CRSloan(std::vector<size_t>& newIndex,std::vector<std::vector<size_t> >& vvConnection,size_t dim,
211  size_t minpind,bool bseparate,bool orderp,bool orderv);
212 
214 template <typename TDomain,typename TGridFunction>
215 void CROrderSloan(ApproximationSpace<TDomain>& approxSpace,TGridFunction& u,
216  bool bseparate,bool orderp,bool orderv)
217 {
219  typedef typename TGridFunction::domain_type domain_type;
220 
222  static const int dim = domain_type::dim;
223 
225  typedef typename TGridFunction::template dim_traits<dim>::grid_base_object elem_type;
226 
227  std::vector<std::vector<size_t> > vvConnection;
228  size_t minpind;
229 
230  for (int si=0;si<u.num_subsets();++si){
231  if (u.num_fct(si)<2){
232  if (u.num_fct(si)!=dim+1){
233  UG_THROW("Wrong number of components in approximation space. Needed " << dim+1 << ", given " << u.num_fct(si) << ".\n");
234  }
235  }
236  for (int d=0;d<dim;d++){
237  if (u.local_finite_element_id(d) != LFEID(LFEID::CROUZEIX_RAVIART, dim, 1)){
238  UG_THROW("Component " << d << " in approximation space must be of Crouzeix-Raviart type.");
239  }
240  }
241  if (u.local_finite_element_id(dim) != LFEID(LFEID::PIECEWISE_CONSTANT, dim, 0)){
242  UG_THROW("Component dim in approximation space must be of piecewise constant type.");
243  }
244  }
245 
246  std::vector<SmartPtr<DoFDistribution> > vDD = approxSpace.dof_distributions();
247  for(size_t i = 0; i < vDD.size(); ++i){
248  std::vector<size_t> newIndex;
249  cr_get_connections<elem_type,TGridFunction>(vvConnection,minpind,*vDD[i],u);
250  CRSloan(newIndex,vvConnection,dim,minpind,bseparate,orderp,orderv);
251  vDD[i]->permute_indices(newIndex);
252  }
253 }
254 
255 void CRKing(std::vector<size_t>& newIndex,std::vector<std::vector<size_t> >& vvConnection,size_t dim,
256  size_t minpind,bool bReverse,bool bseparate,bool orderp,bool orderv);
257 
259 template <typename TDomain,typename TGridFunction>
260 void CROrderKing(ApproximationSpace<TDomain>& approxSpace,TGridFunction& u,
261  bool bReverse,bool bseparate,bool orderp,bool orderv)
262 {
264  typedef typename TGridFunction::domain_type domain_type;
265 
267  static const int dim = domain_type::dim;
268 
270  typedef typename TGridFunction::template dim_traits<dim>::grid_base_object elem_type;
271 
272  std::vector<std::vector<size_t> > vvConnection;
273  size_t minpind;
274 
275  for (int si=0;si<u.num_subsets();++si){
276  if (u.num_fct(si)<2){
277  if (u.num_fct(si)!=dim+1){
278  UG_THROW("Wrong number of components in approximation space. Needed " << dim+1 << ", given " << u.num_fct(si) << ".\n");
279  }
280  }
281  for (int d=0;d<dim;d++){
282  if (u.local_finite_element_id(d) != LFEID(LFEID::CROUZEIX_RAVIART, dim, 1)){
283  UG_THROW("Component " << d << " in approximation space must be of Crouzeix-Raviart type.");
284  }
285  }
286  if (u.local_finite_element_id(dim) != LFEID(LFEID::PIECEWISE_CONSTANT, dim, 0)){
287  UG_THROW("Component dim in approximation space must be of piecewise constant type.");
288  }
289  }
290 
291  std::vector<SmartPtr<DoFDistribution> > vDD = approxSpace.dof_distributions();
292  for(size_t i = 0; i < vDD.size(); ++i){
293  std::vector<size_t> newIndex;
294  cr_get_connections<elem_type,TGridFunction>(vvConnection,minpind,*vDD[i],u);
295  CRKing(newIndex,vvConnection,dim,minpind,bReverse,bseparate,orderp,orderv);
296  vDD[i]->permute_indices(newIndex);
297  }
298 }
299 
300 void CRMinimumDegree(std::vector<size_t>& newIndex,std::vector<std::vector<size_t> >& vvConnection,size_t dim,
301  size_t minpind,bool bseparate,bool orderp,bool orderv);
302 
304 template <typename TDomain,typename TGridFunction>
305 void CROrderMinimumDegree(ApproximationSpace<TDomain>& approxSpace,TGridFunction& u,
306  bool bseparate,bool orderp,bool orderv)
307 {
309  typedef typename TGridFunction::domain_type domain_type;
310 
312  static const int dim = domain_type::dim;
313 
315  typedef typename TGridFunction::template dim_traits<dim>::grid_base_object elem_type;
316 
317  std::vector<std::vector<size_t> > vvConnection;
318  size_t minpind;
319 
320  for (int si=0;si<u.num_subsets();++si){
321  if (u.num_fct(si)<2){
322  if (u.num_fct(si)!=dim+1){
323  UG_THROW("Wrong number of components in approximation space. Needed " << dim+1 << ", given " << u.num_fct(si) << ".\n");
324  }
325  }
326  for (int d=0;d<dim;d++){
327  if (u.local_finite_element_id(d) != LFEID(LFEID::CROUZEIX_RAVIART, dim, 1)){
328  UG_THROW("Component " << d << " in approximation space must be of Crouzeix-Raviart type.");
329  }
330  }
331  if (u.local_finite_element_id(dim) != LFEID(LFEID::PIECEWISE_CONSTANT, dim, 0)){
332  UG_THROW("Component dim in approximation space must be of piecewise constant type.");
333  }
334  }
335 
336  std::vector<SmartPtr<DoFDistribution> > vDD = approxSpace.dof_distributions();
337  for(size_t i = 0; i < vDD.size(); ++i){
338  std::vector<size_t> newIndex;
339  cr_get_connections<elem_type,TGridFunction>(vvConnection,minpind,*vDD[i],u);
340  CRMinimumDegree(newIndex,vvConnection,dim,minpind,bseparate,orderp,orderv);
341  vDD[i]->permute_indices(newIndex);
342  }
343 }
344 
345 // original CR cuthill McKee without boost (faster)
346 void ComputeCRCuthillMcKeeOrder(std::vector<size_t>& vNewIndex,
347  std::vector<std::vector<size_t> >& vvConnections,
348  size_t minpind,
349  bool bReverse);
350 
352 template <typename TDomain,typename TGridFunction>
353 void OrderCRCuthillMcKee(ApproximationSpace<TDomain>& approxSpace,TGridFunction& u,
354  bool bReverse)
355 {
357  typedef typename TGridFunction::domain_type domain_type;
358 
360  static const int dim = domain_type::dim;
361 
363  typedef typename TGridFunction::template dim_traits<dim>::grid_base_object elem_type;
364 
365  for (int si=0;si<u.num_subsets();++si){
366  if (u.num_fct(si)<2){
367  if (u.num_fct(si)!=dim+1){
368  UG_THROW("Wrong number of components in approximation space. Needed " << dim+1 << ", given " << u.num_fct(si) << ".\n");
369  }
370  }
371  for (int d=0;d<dim;d++){
372  if (u.local_finite_element_id(d) != LFEID(LFEID::CROUZEIX_RAVIART, dim, 1)){
373  UG_THROW("Component " << d << " in approximation space must be of Crouzeix-Raviart type.");
374  }
375  }
376  if (u.local_finite_element_id(dim) != LFEID(LFEID::PIECEWISE_CONSTANT, dim, 0)){
377  UG_THROW("Component dim in approximation space must be of piecewise constant type.");
378  }
379  }
380 
381  std::vector<SmartPtr<DoFDistribution> > vDD = approxSpace.dof_distributions();
382  for(size_t i = 0; i < vDD.size(); ++i){
383  // get adjacency graph
384  std::vector<std::vector<size_t> > vvConnection;
385  size_t minpind;
386  cr_get_connections<elem_type,TGridFunction>(vvConnection,minpind,*vDD[i],u);
387  // get mapping for cuthill-mckee order
388  std::vector<size_t> vNewIndex;
389  ComputeCRCuthillMcKeeOrder(vNewIndex,vvConnection,minpind,bReverse);
390  // reorder indices
391  vDD[i]->permute_indices(vNewIndex);
392  }
393 }
394 
395 } // end namespace ug
396 
397 #endif /* __H__UG__PLUGINS__NAVIER_STOKES__INCOMPRESSIBLE__FVCR__CR_REORDER__ */
void indices(GridObject *elem, LocalIndices &ind, bool bHang=false) const
traits< TElem >::iterator begin()
size_t num_indices() const
traits< TElem >::iterator end()
std::vector< SmartPtr< DoFDistribution > > dof_distributions() const
index_type & index(size_t fct, size_t dof)
static const int dim
StringTable s
#define UG_THROW(msg)
double number
int degree(int v, ug::BidirectionalMatrix< T > const &M)
IndexLayout::Interface::iterator find(IndexLayout::Interface &interface, size_t i)
void CRKing(std::vector< size_t > &newIndex, std::vector< std::vector< size_t > > &vvConnection, size_t dim, size_t minpind, bool bReverse, bool bseparate, bool orderp, bool orderv)
orders the dof distribution using King
Definition: cr_reorder.cpp:362
void CRCuthillMcKee(std::vector< size_t > &newIndex, std::vector< std::vector< size_t > > &vvConnection, size_t dim, size_t minpind, bool bReverse, bool bseparate, bool orderp, bool orderv)
orders the dof distribution using Cuthill-McKee
Definition: cr_reorder.cpp:195
void CROrderKing(ApproximationSpace< TDomain > &approxSpace, TGridFunction &u, bool bReverse, bool bseparate, bool orderp, bool orderv)
orders the all DofDistributions of the ApproximationSpace using Cuthill-McKee
Definition: cr_reorder.h:260
void CRSloan(std::vector< size_t > &newIndex, std::vector< std::vector< size_t > > &vvConnection, size_t dim, size_t minpind, bool bseparate, bool orderp, bool orderv)
orders the dof distribution using Sloan
Definition: cr_reorder.cpp:254
void cr_get_connections(std::vector< std::vector< size_t > > &vvConnection, size_t &minpind, DoFDistribution &dd, TGridFunction &u)
Definition: cr_reorder.h:68
void CROrderMinimumDegree(ApproximationSpace< TDomain > &approxSpace, TGridFunction &u, bool bseparate, bool orderp, bool orderv)
orders the all DofDistributions of the ApproximationSpace using minimum degree algorithm
Definition: cr_reorder.h:305
void ComputeCRCuthillMcKeeOrder(std::vector< size_t > &vNewIndex, std::vector< std::vector< size_t > > &vvConnections, size_t minpind, bool bReverse)
Definition: cr_reorder.cpp:510
void CRMinimumDegree(std::vector< size_t > &newIndex, std::vector< std::vector< size_t > > &vvConnection, size_t dim, size_t minpind, bool bseparate, bool orderp, bool orderv)
orders the dof distribution using minimum degree algorithm
Definition: cr_reorder.cpp:422
void CROrderSloan(ApproximationSpace< TDomain > &approxSpace, TGridFunction &u, bool bseparate, bool orderp, bool orderv)
orders the all DofDistributions of the ApproximationSpace using Sloan
Definition: cr_reorder.h:215
void CROrderCuthillMcKee(ApproximationSpace< TDomain > &approxSpace, TGridFunction &u, bool bReverse, bool bseparate, bool orderp, bool orderv)
orders the all DofDistributions of the ApproximationSpace using Cuthill-McKee
Definition: cr_reorder.h:168
void extractVGraph(TGraph &G, std::vector< std::vector< size_t > > &vvConnection, size_t pmin, size_t dim, bool directed)
Definition: cr_reorder.h:149
void OrderCRCuthillMcKee(ApproximationSpace< TDomain > &approxSpace, TGridFunction &u, bool bReverse)
orders the all DofDistributions of the ApproximationSpace using Cuthill-McKee
Definition: cr_reorder.h:353
void computeDegree(std::vector< size_t > &degree, std::vector< std::vector< size_t > > &vvConnections, size_t minpind)
Definition: cr_reorder.cpp:180
void extractPGraph(TGraph &G, std::vector< std::vector< size_t > > &vvConnection, size_t pmin, size_t dim, bool directed)
Definition: cr_reorder.h:136
Definition: cr_reorder.h:49
const std::vector< size_t > & m_degree
storage field of connections of each index
Definition: cr_reorder.h:61
bool operator()(size_t i, size_t j)
comparison operator
Definition: cr_reorder.h:54
CompareDeg(const std::vector< size_t > &vInfo)
constructor, passing field with connections for each index
Definition: cr_reorder.h:51
SurfaceView::traits< TElem >::const_iterator const_iterator