Loading [MathJax]/extensions/tex2jax.js
Plugins
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
42namespace ug{
43
49struct 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
59private:
61 const std::vector<size_t>& m_degree;
62};
63
64void 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
67template <typename TElem, typename TGridFunction>
68void 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
135template <class TGraph>
136void 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
148template <class TGraph>
149void 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
163void 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
167template <typename TDomain,typename TGridFunction>
168void 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
210void 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
214template <typename TDomain,typename TGridFunction>
215void 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
255void 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
259template <typename TDomain,typename TGridFunction>
260void 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
300void 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
304template <typename TDomain,typename TGridFunction>
305void 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)
346void ComputeCRCuthillMcKeeOrder(std::vector<size_t>& vNewIndex,
347 std::vector<std::vector<size_t> >& vvConnections,
348 size_t minpind,
349 bool bReverse);
350
352template <typename TDomain,typename TGridFunction>
353void 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__ */
parameterString s
Definition Biogas.lua:2
traits< TElem >::iterator begin()
traits< TElem >::iterator end()
void indices(GridObject *elem, LocalIndices &ind, bool bHang=false) const
size_t num_indices() const
std::vector< SmartPtr< DoFDistribution > > dof_distributions() const
index_type & index(size_t fct, size_t dof)
#define UG_THROW(msg)
double number
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