NeoPZ
TPZSloanRenumbering.cpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------
2 
3 #include "TPZSloanRenumbering.h"
4 #include "TPZCutHillMcKee.h"
5 
6 TPZSloanRenumbering::TPZSloanRenumbering(int64_t NElements, int64_t NNodes):TPZRenumbering(NElements,NNodes){
7 
8 }
9 
11 }
12 
13 
15 
16 }
17 
18 //#define DEBUG_SLOAN_RENUMBERING
19 #ifdef PZDEBUG_SLOAN_RENUMBERING
20 #include <fstream>
21 std::ofstream myfile("c:\\Temp\\sloanrenumbering.txt");
22 #endif
24 
25 #ifdef PZDEBUG_SLOAN_RENUMBERING
26  time_t StartTime = time(NULL);
27 #endif
28 
29 
30  //computing graph
33  graph.fnodegraph.Shrink();
34  graph.fnodegraphindex.Shrink();
35 
36 #ifdef PZDEBUG_SLOAN_RENUMBERING
37  {
38  time_t finalTime = time(NULL);
39  const double elapsedtime = difftime(finalTime, StartTime);
40  myfile << "Tempo ConvertGraph = " << elapsedtime << "\n";
41  myfile.flush();
42  StartTime = time(NULL);
43  }
44 #endif
45 
46  //finding pseudo peripheral nodes
47  const int64_t nnodes = graph.NNodes();
48  int64_t startNode = -1, endNode = -1;
49  graph.PseudoPeripheralNodes(startNode, endNode);
50 
51  //computing distances to end node
52  TPZStack< TPZStack<int64_t> > LevelStructure;
53  graph.RootedLevelStructure(endNode, LevelStructure);
54  TPZManVector<int64_t> DistanceToEndNode( nnodes, -1 );
55  int64_t nelslevel = LevelStructure.NElements();
56  for(int64_t ilevel = 0; ilevel < nelslevel; ilevel++){
57  int64_t nelsilevel= LevelStructure[ ilevel ].NElements();
58  for(int64_t iel = 0; iel < nelsilevel; iel++){
59  const int64_t node = LevelStructure[ ilevel ][ iel ];
60  DistanceToEndNode[ node ] = ilevel;
61  }//for iel
62  }//for ilevel
63 #ifdef PZDEBUG
64  for(int64_t i = 0; i < DistanceToEndNode.NElements(); i++){
65  if(DistanceToEndNode[i] == -1){
66  DebugStop();
67  }
68  }
69 #endif
70 
71 // std::cout << "Computed DistanceToEndNode\n";
72  //assigning initial status and priority
73  int64_t maxpriority = 0;
74  TPZVec<int64_t> priority( nnodes, -1);
75  for(int64_t i = 0; i < nnodes; i++){
76  const int64_t degree = graph.Degree(i);
77  priority[i] = this->W1()*DistanceToEndNode[i] - this->W2()*(degree+1);
78  maxpriority = MAX(maxpriority,priority[i]);
79  }//for i
80 
81  TPZVec<int64_t> Status(nnodes,EInactive);
83  R.Resize(nnodes);//pre allocating memory
84  R.Resize(0);
85 
86 // TPZManVector<int64_t,10000> adjNodes, adjNodes2J;
87  SList Q(nnodes);
88  Status[startNode] = EPreActive;
89  Q.push_back( startNode );
90  while(Q.fSize){
91  int64_t index;
92  maxpriority = 0;
93  const int64_t currnode = this->FindHighestPriority(Q,priority,index);
94  maxpriority = MAX(maxpriority,priority[currnode]);
95  Q.remove(index);
96  if(Status[currnode] == EPreActive){
97  int64_t nadjNodes;
98  int64_t * adjNodePtr = graph.AdjacentNodesPtr(currnode, nadjNodes);
99  for(int64_t jadj = 0; jadj < nadjNodes; jadj++){
100  const int64_t adjNode = adjNodePtr[jadj];
101  priority[ adjNode ] += this->W2();//no artigo de 86 o sloan soma W1, no de de 89 soma W2. To seguindo a notacao de 89
102  if(Q.push_back(adjNode) == true && Status[adjNode] == EInactive){
103  Status[ adjNode] = EPreActive;
104  maxpriority = MAX(maxpriority,priority[adjNode]);
105  //ja foi inserido no if acima Q.push_back( adjNode );
106  }
107  }//jadj
108  }//not a preactive node
109  R.Push( currnode );
110  Status[ currnode ] = EPostActive;
111 
112  //step 9: updating priorities and queue
113  int64_t nadjNodes;
114  int64_t * adjNodePtr = graph.AdjacentNodesPtr(currnode, nadjNodes);
115  for(int64_t jadj = 0; jadj < nadjNodes; jadj++){
116  const int64_t adjNode = adjNodePtr[jadj];
117  if( Status[ adjNode ] == EPreActive ){
118  Status[ adjNode ] = EActive;
119  priority[ adjNode ] += this->W2();//no artigo de 86 o sloan soma W1, no de de 89 soma W2. To seguindo a notacao de 89
120  maxpriority = MAX(maxpriority,priority[adjNode]);
121  int64_t nadjNodes2J;
122  int64_t * adjNode2JPtr = graph.AdjacentNodesPtr(adjNode, nadjNodes2J);
123  for(int64_t k = 0; k < nadjNodes2J; k++){
124  const int64_t knode = adjNode2JPtr[k];
125  if(Status[knode] != EPostActive){
126  int pr = priority[knode];
127  priority[knode] = pr+this->W2();
128  maxpriority = MAX(maxpriority,priority[knode]);
129  }//if ! post active
130  if( Q.push_back(knode) == true && Status[knode] == EInactive){
131  Status[knode] = EPreActive;
132  //ja foi inserido no if acima Q.push_back( knode );
133  }// if inactive
134  }//loop of k nodes
135  }//if
136  }//for jadj
137 
138  if(R.NElements() % 100000 == 0){
139  std::cout << R.NElements() << "\tQ.size = " << Q.fSize << ", %done = " << 100.*R.NElements()/nnodes << " maxpriority = " << maxpriority << "\n";
140  }
141  }//while
142 
143  if(R.NElements() != nnodes){
144  std::cout << "TPZSloanRenumbering::Resequence error! Not all nodes were processed.\n"
145  << "It may be an implementation bug or simply a graph with independent nodes\n"
146  << "as if the mesh has subdomains that are not connected.\n"
147  << "For the later, use CuttHillMcKee, which is prepared for this particular case\n";
148  DebugStop();
149  }
150 
151 #ifdef PZDEBUG
152 {//verificando se ha duplicados
153  std::set<int64_t> check;
154  for(int64_t i = 0; i < nnodes; i++) check.insert(R[i]);
155  if( ((int64_t)(check.size())) != nnodes) DebugStop();
156 }
157 #endif
158 
159  permScatter = R;
160  permGather.Resize(nnodes);
161  for(int64_t i = 0; i < nnodes; i++) permGather[ permScatter[i] ] = i;
162 
163 #ifdef PZDEBUG_SLOAN_RENUMBERING
164  {
165  time_t finalTime = time(NULL);
166  const double elapsedtime = difftime(finalTime, StartTime);
167  myfile << "Tempo restante = " << elapsedtime << "\n\n\n";
168  myfile.flush();
169  StartTime = time(NULL);
170  }
171 #endif
172 
173 
174 }//void
175 
176 int64_t TPZSloanRenumbering::FindHighestPriority(const SList &Q, const TPZVec<int64_t> &priority, int64_t &Qindex) const{
177  if(Q.fSize == 0) DebugStop();
178  int64_t result = Q.fList[0];
179  int64_t nodepriority = priority[result];
180  Qindex = 0;
181  for(int64_t i = 1; i < Q.fSize; i++){
182  const int64_t lcnode = Q.fList[i];
183  if(priority[lcnode] > nodepriority){
184  result = lcnode;
185  nodepriority = priority[lcnode];
186  Qindex = i;
187  }
188  }
189  return result;
190 
191 }//int64_t
192 
193 
195 {
196  //computing graph
199  graph.fnodegraph.Shrink();
200  graph.fnodegraphindex.Shrink();
201 
202  //finding pseudo peripheral nodes
203  const int64_t nnodes = graph.NNodes();
204 
205  fAllNodes.Resize(nnodes);
206  for (int64_t i=0; i<nnodes; i++) {
207  fAllNodes[i].fIndex = i;
208  }
209 
210 
211  int64_t startNode = -1, endNode = -1;
212  graph.PseudoPeripheralNodes(startNode, endNode);
213 
214  //computing distances to end node
215  TPZStack< TPZStack<int64_t> > LevelStructure;
216  graph.RootedLevelStructure(endNode, LevelStructure);
217  TPZVec<int> DistanceToEndNode( nnodes, -1 );
218  for(int64_t ilevel = 0; ilevel < LevelStructure.NElements(); ilevel++){
219  for(int64_t iel = 0; iel < LevelStructure[ ilevel ].NElements(); iel++){
220  const int64_t node = LevelStructure[ ilevel ][ iel ];
221  DistanceToEndNode[ node ] = ilevel;
222  }//for iel
223  }//for ilevel
224 #ifdef PZDEBUG
225  for(int64_t i = 0; i < DistanceToEndNode.NElements(); i++){
226  if(DistanceToEndNode[i] == -1){
227  DebugStop();
228  }
229  }
230 #endif
231 
232 // std::cout << "Computed DistanceToEndNode\n";
233  //assigning initial status and priority
234  for(int64_t i = 0; i < nnodes; i++){
235  const int degree = graph.Degree(i);
236  fAllNodes[i].fPriority = this->W1()*DistanceToEndNode[i] - this->W2()*(degree+1);
237  }//for i
238 
239  int64_t countnumbered = 0;
240  int64_t numactive = 1;
241  fAllNodes[startNode].fStatus = EPreActive;
242  InsertNode(&fAllNodes[startNode]);
243 
244  while (fActive.size())
245  {
246  TNo *worknode = PopHighestPriorityNode();
247  numactive--;
248 
249  if (worknode->fStatus == EPreActive)
250  {
251  int64_t nadjNodes;
252  int64_t * adjNodePtr = graph.AdjacentNodesPtr(worknode->fIndex, nadjNodes);
253  for(int64_t jadj = 0; jadj < nadjNodes; jadj++){
254  const int64_t adjNode = adjNodePtr[jadj];
255  if (fAllNodes[adjNode].fStatus == EInactive) {
256  fAllNodes[adjNode].fPriority += this->W2();
257  fAllNodes[adjNode].fStatus = EPreActive;
258  InsertNode(&fAllNodes[adjNode]);
259  numactive++;
260  }
261  else if(fAllNodes[adjNode].fStatus != EPostActive)
262  {
263  int priority = fAllNodes[adjNode].fPriority;
264  priority += this->W2();
265  TransferPriority(&fAllNodes[adjNode],priority);
266  }
267  }
268  }
269  worknode->fStatus = EPostActive;
270  worknode->fSequenceNumber = countnumbered;
271  countnumbered++;
272 
273  //step 9: updating priorities and queue
274  int64_t nadjNodes;
275  int64_t * adjNodePtr = graph.AdjacentNodesPtr(worknode->fIndex, nadjNodes);
276  for(int64_t jadj = 0; jadj < nadjNodes; jadj++){
277  const int64_t adjNode = adjNodePtr[jadj];
278  if( fAllNodes[ adjNode ].fStatus == EPreActive ){
279  fAllNodes[ adjNode ].fStatus = EActive;
280  int priority = fAllNodes[adjNode].fPriority;
281  priority += this->W2();//no artigo de 86 o sloan soma W1, no de de 89 soma W2. To seguindo a notacao de 89
282  TransferPriority(&fAllNodes[adjNode], priority);
283  int64_t nadjNodes2J;
284  int64_t * adjNode2JPtr = graph.AdjacentNodesPtr(adjNode, nadjNodes2J);
285  for(int64_t k = 0; k < nadjNodes2J; k++){
286  const int64_t knode = adjNode2JPtr[k];
287  if(fAllNodes[knode].fStatus != EPostActive){
288  int priority = fAllNodes[knode].fPriority;
289  priority += this->W2();
290  if (fAllNodes[knode].fStatus == EInactive) {
291  fAllNodes[knode].fPriority = priority;
292  InsertNode(&fAllNodes[knode]);
293  fAllNodes[knode].fStatus = EPreActive;
294  numactive++;
295  }
296  else
297  {
298  TransferPriority(&fAllNodes[knode], priority);
299  }
300  }//if ! post active
301  }//loop of k nodes
302  }//if
303  }//for jadj
304 
305  if(countnumbered % 1000000 == 0){
306  std::cout << countnumbered << "\tActive size = " << numactive << ", %done = " << 100.*countnumbered/nnodes << "\n";
307  }
308 
309  }
310  std::cout << "number of elements sequenced " << countnumbered << std::endl;
311 }
312 
int64_t NElements() const
Number of computational elements allocated.
Definition: pzcmesh.h:169
std::map< int, TNo * > fActive
int64_t FindHighestPriority(const SList &Q, const TPZVec< int64_t > &priority, int64_t &Qindex) const
TPZManVector< int64_t > fnodegraph
void ConvertGraph(TPZVec< int64_t > &elgraph, TPZVec< int64_t > &elgraphindex, TPZManVector< int64_t > &nodegraph, TPZManVector< int64_t > &nodegraphindex)
Will convert an element graph defined by elgraph and elgraphindex into a node graph defined by nodegr...
virtual void Resequence2(TPZVec< int64_t > &permGather, TPZVec< int64_t > &permScatter)
void degree(int root, int adj_num, int adj_row[], int adj[], int mask[], int deg[], int *iccsze, int ls[], int node_num)
Definition: rcm.cpp:875
int64_t Degree(int64_t node)
#define MAX(a, b)
Gets maxime value between a and b.
Definition: pzreal.h:81
virtual void Resize(const int64_t newsize, const T &object)
Resizes the vector object.
Definition: pzmanvector.h:426
void RootedLevelStructure(int64_t rootNode, TPZStack< TPZStack< int64_t > > &LevelStructure)
TPZVec< int64_t > fElementGraphIndex
Indicates for each element the index of the first entry with fElementGraph for that element The size ...
virtual void Resize(const int64_t newsize, const T &object)
Resizes the vector object reallocating the necessary storage, copying the existing objects to the new...
Definition: pzvec.h:373
void Push(const T object)
Pushes a copy of the object on the stack.
Definition: pzstack.h:80
This abstract class which defines the behavior which derived classes need to implement for implement...
#define DebugStop()
Returns a message to user put a breakpoint in.
Definition: pzerror.h:20
void TransferPriority(TNo *no, int newpriority)
void InsertNode(TNo *node)
virtual void Resequence(TPZVec< int64_t > &permGather, TPZVec< int64_t > &permScatter)
void Shrink()
It reallocates storage to fit the necessary storage exactly.
Definition: pzmanvector.h:388
TPZVec< int64_t > fElementGraph
Node number of each element.
TPZManVector< int64_t > fnodegraphindex
This class implements a stack object. Utility.
Definition: pzcheckmesh.h:14
int64_t * AdjacentNodesPtr(int64_t parent, int64_t &n)
int64_t NElements() const
Returns the number of elements of the vector.
Definition: pzvec.h:190
void PseudoPeripheralNodes(int64_t &startNode, int64_t &endNode)