📄 graph.c
字号:
#define RCSID "$Id: Graph.c,v 1.3 2006/02/26 00:42:52 geuzaine Exp $"/* * Copyright (C) 1997-2006 P. Dular, C. Geuzaine * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. * * Please report all bugs and problems to <getdp@geuz.org>. * * Contributor(s): * David Colignon */#include "GetDP.h"#include "Graph.h"#include "DofData.h"#include "Compat.h"/* Si on est sur d'utiliser Metis tout le temps, on devrait definir correctement la strcture de Graphe avec idxtype*//* ------------------------------------------------------------------------ *//* private functions *//* ------------------------------------------------------------------------ */static int Graph_cmpij(int ai,int aj,int bi,int bj){ if(ai<bi) return -1; if(ai>bi) return 1; if(aj<bj) return -1; if(aj>bj) return 1; return 0;}static int *alloc_ivec(long nl, long nh){ int *v; v=(int *)Malloc((size_t) ((nh-nl+1+1)*sizeof(int))); return v-nl+1;}static void free_ivec(int *v, long nl, long nh){ Free(v+nl-1);}#define SWAP(a,b) temp=(a);(a)=(b);(b)=temp;#define SWAPI(a,b) tempi=(a);(a)=(b);(b)=tempi;#define M 7#define NSTACK 50#define M1 -1static void Graph_sort(unsigned long n, int ai[] , int aj []){ unsigned long i,ir=n,j,k,l=1; int *istack,jstack=0,tempi; int b,c; GetDP_Begin("Graph_sort"); istack=alloc_ivec(1,NSTACK); for (;;) { if (ir-l < M) { for (j=l+1;j<=ir;j++) { b=ai[j M1]; c=aj[j M1]; for (i=j-1;i>=1;i--) { if (Graph_cmpij(ai[i M1],aj[i M1],b,c) <= 0) break; ai[i+1 M1]=ai[i M1]; aj[i+1 M1]=aj[i M1]; } ai[i+1 M1]=b; aj[i+1 M1]=c; } if (!jstack) { free_ivec(istack,1,NSTACK); GetDP_End; } ir=istack[jstack]; l=istack[jstack-1]; jstack -= 2; } else { k=(l+ir) >> 1; SWAPI(ai[k M1],ai[l+1 M1]) SWAPI(aj[k M1],aj[l+1 M1]) if (Graph_cmpij(ai[l+1 M1],aj[l+1 M1],ai[ir M1],aj[ir M1])>0){ SWAPI(ai[l+1 M1],ai[ir M1]) SWAPI(aj[l+1 M1],aj[ir M1]) } if (Graph_cmpij(ai[l M1],aj[l M1],ai[ir M1],aj[ir M1])>0){ SWAPI(ai[l M1],ai[ir M1]) SWAPI(aj[l M1],aj[ir M1]) } if (Graph_cmpij(ai[l+1 M1],aj[l+1 M1],ai[l M1],aj[l M1])>0){ SWAPI(ai[l+1 M1],ai[l M1]) SWAPI(aj[l+1 M1],aj[l M1]) } i=l+1; j=ir; b=ai[l M1]; c=aj[l M1]; for (;;) { do i++; while (Graph_cmpij(ai[i M1],aj[i M1],b,c) < 0); do j--; while (Graph_cmpij(ai[j M1],aj[j M1],b,c) > 0); if (j < i) break; SWAPI(ai[i M1],ai[j M1]) SWAPI(aj[i M1],aj[j M1]) } ai[l M1]=ai[j M1]; ai[j M1]=b; aj[l M1]=aj[j M1]; aj[j M1]=c; jstack += 2; if (jstack > NSTACK) { Msg(GERROR, "NSTACK too small in sort2"); } if (ir-i+1 >= j-l) { istack[jstack]=ir; istack[jstack-1]=i; ir=j-1; } else { istack[jstack]=j-1; istack[jstack-1]=l; l=i; } } } GetDP_End ;}#undef M#undef NSTACK#undef SWAP#undef SWAPI#undef M1static void Graph_deblign (int nz , int *ptr , int *jptr , int *ai){ int i,ilign; GetDP_Begin("Graph_deblign"); ilign = 1; jptr[0] = 1; for(i=1; i<nz; i++) { if (ai[i-1] < ai[i]) { jptr[ilign++]=i+1; ai[i-1] = 0; } else{ ai[i-1] = i+1; } } ai[nz-1] = 0; GetDP_End ;}void Graph_csr_format (gGraph *GG, int N){ int i,*ptr,*jptr,*ai,n,iptr,iptr2; GetDP_Begin("Graph_csr_format"); ptr = (int*)GG->ptr->array; jptr = (int*)GG->jptr->array; ai = (int*)GG->ai->array; n = N; for(i=0;i<n;i++){ iptr = jptr[i]; while(iptr){ iptr2 = iptr - 1; iptr = ptr[iptr2]; ptr[iptr2] = i+1; } } Graph_sort(List_Nbr(GG->ai),ai,ptr); Graph_deblign(List_Nbr(GG->ai),ptr,jptr,ai); jptr[N]=List_Nbr(GG->ai)+1; GetDP_End ;} void Graph_restore_format (gGraph *GG){ char *temp; GetDP_Begin("Graph_restore_format"); temp = GG->ptr->array; GG->ptr->array = GG->ai->array; GG->ai->array = temp; GetDP_End ;} /* ------------------------------------------------------------------------ *//* public functions *//* ------------------------------------------------------------------------ */void InitGraph (int NbLines, gGraph *G){ int i, j=0; GetDP_Begin("InitGraph"); G->ai = List_Create (NbLines, NbLines, sizeof(int)); G->ptr = List_Create (NbLines, NbLines, sizeof(int)); G->jptr = List_Create (NbLines+1, NbLines, sizeof(int)); /* '+1' indispensable: csr_format ecrit 'nnz+1' dans jptr[NbLine] */ for(i=0; i<NbLines; i++) List_Add (G->jptr, &j); GetDP_End ;}/* attention a la transposition ! */void AddEdgeInGraph (gGraph *G, int ic, int il){ int *ai, *pp, n, iptr, iptr2, jptr, *ptr, zero = 0; GetDP_Begin("AddEdgeInGraph"); il--; pp = (int*) G->jptr->array; ptr = (int*) G->ptr->array; ai = (int*) G->ai->array; iptr = pp[il]; iptr2 = iptr-1; while(iptr>0){ iptr2 = iptr-1; jptr = ai[iptr2]; if(jptr == ic){ GetDP_End; } iptr = ptr[iptr2]; } List_Add (G->ai, &ic); List_Add (G->ptr, &zero); /* Les pointeurs ont pu etre modifies s'il y a eu une reallocation dans List_Add */ ptr = (int*) G->ptr->array; ai = (int*) G->ai->array; n = List_Nbr(G->ai); if(!pp[il]) pp[il] = n; else ptr[iptr2] = n; GetDP_End ;}#if defined(HAVE_METIS)EXTERN_C_BEGIN#include "metis.h"EXTERN_C_ENDvoid PartitionGraph(struct DofData * DofData_P, int NbPartition){ int i; int n9, wgtflag9, numflag9, options9[5]; int edgecut9; int *part_P, *cptr_P, *start_P; /* int kd, kf, kk, cptr, options8[8] ; int *ia, *ja, *ia_N, *ja_N, trente=30, zero=0, trenteetun=31, trentedeux=32; */ idxtype *xadj9, *adjncy9, *part9, *perm9, *iperm9; struct Dof * Dof_P ; GetDP_Begin("PartitionGraph"); Graph_csr_format (&DofData_P->Graph, List_Nbr(DofData_P->Graph.jptr)); Graph_restore_format (&DofData_P->Graph); n9 = List_Nbr(DofData_P->Graph.jptr); /* ia = (int*) DofData_P->Graph.jptr->array; ja = (int*) DofData_P->Graph.ai->array; psplot_(&n9, ja, ia, &trente, &zero); */ xadj9 = (idxtype*) DofData_P->Graph.jptr->array; adjncy9 = (idxtype*) DofData_P->Graph.ai->array; numflag9 = 1; perm9 = (idxtype*) Malloc( n9 * sizeof(idxtype)); iperm9 = (idxtype*) Malloc( n9 * sizeof(idxtype)); /* si Flag_PAR = 1, on n'arrive meme pas jusqu'ici car if (Flag_PAR > 1) dans SolvingAnalyse if ( NbPartition == 1 ) { options8[0] = 0 ; METIS_NodeND( &n9, xadj9, adjncy9, &numflag9, options8, perm9, iperm9); Msg(PETSC, "METIS Renumbering done") ; DofData_P->NbrPart = NbPartition ; DofData_P->Part[0] = 1 ; DofData_P->Part[1] = DofData_P->NbrDof+1 ; } else { */ wgtflag9 = 0; options9[0] = 0; part9 = (idxtype*) Malloc( n9 * sizeof(idxtype)); METIS_PartGraphRecursive( &n9, xadj9, adjncy9, NULL, NULL, &wgtflag9, &numflag9, &NbPartition, options9, &edgecut9, part9); Msg(PETSC, "METIS partitionning done (edgecut = %d)", edgecut9) ; Free(adjncy9); part_P = (int*) Malloc( (NbPartition) * sizeof(int)); cptr_P = (int*) Malloc( (NbPartition) * sizeof(int)); for ( i = 1 ; i <= NbPartition ; i++ ) { part_P[i-1] = 0; /* Taille de la partition */ cptr_P[i-1] = 0; } for ( i = 1 ; i <= n9 ; i++ ) { part_P[part9[i-1]-1]++; iperm9[i-1] = 0; } start_P = (int*) Malloc( (NbPartition) * sizeof(int)); start_P[0] = 0; for ( i = 2 ; i <= NbPartition ; i++ ) start_P[i-1] = start_P[i-1-1]+part_P[i-1-1]; for ( i = 1 ; i <= n9 ; i++ ) { cptr_P[part9[i-1]-1]++; iperm9[i-1] = start_P[part9[i-1]-1]+cptr_P[part9[i-1]-1]; perm9[iperm9[i-1]-1] = i; } Free(part9); Free(cptr_P); DofData_P->NbrPart = NbPartition ; for (i=1 ; i <= NbPartition ; i++) { DofData_P->Part[i-1] = start_P[i-1]+1 ; Msg(PETSC, "Partition %d: length = %d ",i,part_P[i-1]); } DofData_P->Part[NbPartition] = DofData_P->NbrDof+1 ; Free(part_P); Free(start_P); /* } */ /* Si on veut imprimer le masque de la matrice, il faut retrier le graphe ... ia_N = (int*) Malloc( (n9+1) * sizeof(int)); ja_N = (int*) Malloc( (List_Nbr(DofData_P->Graph.ai)) * sizeof(int)); cptr = 1 ; for (i = 1 ; i <= n9 ; i++) { ia_N[i-1] = cptr; kd = ia[perm9[i-1]-1]; kf = ia[perm9[i-1]+1-1]-1; for (kk = 1 ; kk <= (kf-kd+1) ; kk++) { if (NbPartition == 1 ) ja_N[cptr+kk-1-1] = iperm9[ja[kd+kk-1-1]-1]; else ja_N[cptr+kk-1-1] = ja[kd+kk-1-1]; } cptr = cptr+kf-kd+1; } ia_N[i-1] = cptr; psplot_(&n9, ja_N, ia_N, &trenteetun, &zero); */ for (i = 0 ; i < List_Nbr(DofData_P->DofList) ; i++) { Dof_P=(struct Dof *) List_Pointer(DofData_P->DofList,i); switch (Dof_P->Type) { case DOF_UNKNOWN : Dof_P->Case.Unknown.NumDof = iperm9[Dof_P->Case.Unknown.NumDof-1]; break; case DOF_FIXED : case DOF_FIXEDWITHASSOCIATE : break; default : Msg(GERROR,"Strange stuff in partitioning"); break; } } for(i = 1 ; i<=DofData_P->NbrDof ; i++){ DofData_P->Nnz[i-1] = xadj9[perm9[i-1]-1+1] - xadj9[perm9[i-1]-1] + 1 ; } Free(perm9); Free(iperm9); Free(xadj9); /* free le reste */ GetDP_End ;}#elsevoid PartitionGraph(struct DofData * DofData_P, int NbPartition){ GetDP_Begin("PartitionGraph"); Msg(GERROR, "Impossible to partition (GetDP was compiled without Metis)"); GetDP_End ;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -