1 |
/* $Id$ */ |
2 |
|
3 |
/******************************************************* |
4 |
* |
5 |
* Copyright 2003-2007 by ACceSS MNRF |
6 |
* Copyright 2007 by University of Queensland |
7 |
* |
8 |
* http://esscc.uq.edu.au |
9 |
* Primary Business: Queensland, Australia |
10 |
* Licensed under the Open Software License version 3.0 |
11 |
* http://www.opensource.org/licenses/osl-3.0.php |
12 |
* |
13 |
*******************************************************/ |
14 |
|
15 |
/************************************************************************/ |
16 |
|
17 |
/* Finley: Mesh: optimizes the labeling of the DOFs on each processor */ |
18 |
|
19 |
/************************************************************************/ |
20 |
|
21 |
#include "Mesh.h" |
22 |
#include "IndexList.h" |
23 |
|
24 |
/**************************************************************/ |
25 |
|
26 |
void Finley_Mesh_optimizeDOFLabeling(Finley_Mesh* in,dim_t *distribution) { |
27 |
|
28 |
index_t myFirstVertex,myLastVertex, *newGlobalDOFID=NULL, firstVertex, lastVertex; |
29 |
register index_t k; |
30 |
dim_t mpiSize, myNumVertices,len, p, i; |
31 |
Paso_Pattern *pattern=NULL; |
32 |
Paso_MPI_rank myRank,dest,source,current_rank; |
33 |
Finley_IndexList* index_list=NULL; |
34 |
#ifdef PASO_MPI |
35 |
MPI_Status status; |
36 |
#endif |
37 |
|
38 |
if (in==NULL) return; |
39 |
if (in->Nodes == NULL) return; |
40 |
|
41 |
myRank=in->MPIInfo->rank; |
42 |
mpiSize=in->MPIInfo->size; |
43 |
myFirstVertex=distribution[myRank]; |
44 |
myLastVertex=distribution[myRank+1]; |
45 |
myNumVertices=myLastVertex-myFirstVertex; |
46 |
len=0; |
47 |
for (p=0;p<mpiSize;++p) len=MAX(len,distribution[p+1]-distribution[p]); |
48 |
|
49 |
index_list=TMPMEMALLOC(myNumVertices,Finley_IndexList); |
50 |
newGlobalDOFID=TMPMEMALLOC(len,index_t); |
51 |
/* create the adjacency structure xadj and adjncy */ |
52 |
if (! ( Finley_checkPtr(index_list) || Finley_checkPtr(newGlobalDOFID) ) ) { |
53 |
#pragma omp parallel private(i) |
54 |
{ |
55 |
#pragma omp for schedule(static) |
56 |
for(i=0;i<myNumVertices;++i) { |
57 |
index_list[i].extension=NULL; |
58 |
index_list[i].n=0; |
59 |
} |
60 |
/* insert contributions from element matrices into colums index index_list: */ |
61 |
Finley_IndexList_insertElementsWithRowRangeNoMainDiagonal(index_list, myFirstVertex, myLastVertex, |
62 |
in->Elements,in->Nodes->globalDegreesOfFreedom, |
63 |
in->Nodes->globalDegreesOfFreedom); |
64 |
Finley_IndexList_insertElementsWithRowRangeNoMainDiagonal(index_list, myFirstVertex, myLastVertex, |
65 |
in->FaceElements,in->Nodes->globalDegreesOfFreedom, |
66 |
in->Nodes->globalDegreesOfFreedom); |
67 |
Finley_IndexList_insertElementsWithRowRangeNoMainDiagonal(index_list, myFirstVertex, myLastVertex, |
68 |
in->ContactElements,in->Nodes->globalDegreesOfFreedom, |
69 |
in->Nodes->globalDegreesOfFreedom); |
70 |
Finley_IndexList_insertElementsWithRowRangeNoMainDiagonal(index_list, myFirstVertex, myLastVertex, |
71 |
in->Points,in->Nodes->globalDegreesOfFreedom, |
72 |
in->Nodes->globalDegreesOfFreedom); |
73 |
} |
74 |
/* create the local matrix pattern */ |
75 |
pattern=Finley_IndexList_createPattern(0,myNumVertices,index_list,myFirstVertex, myLastVertex,-myFirstVertex); |
76 |
|
77 |
/* clean up index list */ |
78 |
if (index_list!=NULL) { |
79 |
#pragma omp parallel for private(i) |
80 |
for(i=0;i<myNumVertices;++i) Finley_IndexList_free(index_list[i].extension); |
81 |
} |
82 |
|
83 |
if (Finley_noError()) Paso_Pattern_reduceBandwidth(pattern,newGlobalDOFID); |
84 |
|
85 |
Paso_Pattern_free(pattern); |
86 |
} |
87 |
Paso_MPIInfo_noError(in->MPIInfo); |
88 |
if (Finley_noError()) { |
89 |
/* shift new labeling to create a global id */ |
90 |
#pragma omp parallel for private(i) |
91 |
for (i=0;i<myNumVertices;++i) newGlobalDOFID[i]+=myFirstVertex; |
92 |
|
93 |
|
94 |
/* distribute new labeling to other processors */ |
95 |
dest=Paso_MPIInfo_mod(mpiSize, myRank + 1); |
96 |
source=Paso_MPIInfo_mod(mpiSize, myRank - 1); |
97 |
current_rank=myRank; |
98 |
for (p=0; p< mpiSize; ++p) { |
99 |
firstVertex=distribution[current_rank]; |
100 |
lastVertex=distribution[current_rank+1]; |
101 |
#pragma omp parallel for private(i,k) |
102 |
for (i=0;i<in->Nodes->numNodes;++i) { |
103 |
k=in->Nodes->globalDegreesOfFreedom[i]; |
104 |
if ( (firstVertex<=k) && (k<lastVertex)) { |
105 |
in->Nodes->globalDegreesOfFreedom[i]=newGlobalDOFID[k-firstVertex]; |
106 |
} |
107 |
} |
108 |
|
109 |
if (p<mpiSize-1) { /* the final send can be skipped */ |
110 |
#ifdef PASO_MPI |
111 |
MPI_Sendrecv_replace(newGlobalDOFID,len, MPI_INT, |
112 |
dest, in->MPIInfo->msg_tag_counter, |
113 |
source, in->MPIInfo->msg_tag_counter, |
114 |
in->MPIInfo->comm,&status); |
115 |
#endif |
116 |
in->MPIInfo->msg_tag_counter++; |
117 |
current_rank=Paso_MPIInfo_mod(mpiSize, current_rank-1); |
118 |
} |
119 |
} |
120 |
} |
121 |
TMPMEMFREE(index_list); |
122 |
TMPMEMFREE(newGlobalDOFID); |
123 |
#if 0 |
124 |
for (i=0;i<in->Nodes->numNodes;++i) printf("%d ",in->Nodes->globalDegreesOfFreedom[i]); |
125 |
printf("\n"); |
126 |
#endif |
127 |
return; |
128 |
} |