Skip to content
Snippets Groups Projects
Select Git revision
  • 509e02db33faf9d6cc2a19112382e765ed5b9553
  • master default
  • cgnsUnstructured
  • partitioning
  • poppler
  • HighOrderBLCurving
  • gmsh_3_0_4
  • gmsh_3_0_3
  • gmsh_3_0_2
  • gmsh_3_0_1
  • gmsh_3_0_0
  • gmsh_2_16_0
  • gmsh_2_15_0
  • gmsh_2_14_1
  • gmsh_2_14_0
  • gmsh_2_13_2
  • gmsh_2_13_1
  • gmsh_2_12_0
  • gmsh_2_11_0
  • gmsh_2_10_1
  • gmsh_2_10_0
  • gmsh_2_9_3
  • gmsh_2_9_2
  • gmsh_2_9_1
  • gmsh_2_9_0
  • gmsh_2_8_6
26 results

meshpart.c

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    meshpart.c 5.76 KiB
    /*
     * Copyright 1997, Regents of the University of Minnesota
     *
     * meshpart.c
     *
     * This file contains routines for partitioning finite element meshes.
     *
     * Started 9/29/97
     * George
     *
     * $Id: meshpart.c,v 1.1 2005-09-07 14:36:45 remacle Exp $
     *
     */
    
    #include <metis.h>
    
    
    /*************************************************************************
    * This function partitions a finite element mesh by partitioning its nodal
    * graph using KMETIS and then assigning elements in a load balanced fashion.
    **************************************************************************/
    void METIS_PartMeshNodal(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, 
                             int *nparts, int *edgecut, idxtype *epart, idxtype *npart)
    {
      int i, j, k, me;
      idxtype *xadj, *adjncy, *pwgts;
      int options[10], pnumflag=0, wgtflag=0;
      int nnbrs, nbrind[200], nbrwgt[200], maxpwgt;
      int esize, esizes[] = {-1, 3, 4, 8, 4};
    
      esize = esizes[*etype];
    
      if (*numflag == 1)
        ChangeMesh2CNumbering((*ne)*esize, elmnts);
    
      xadj = idxmalloc(*nn+1, "METIS_MESHPARTNODAL: xadj");
      adjncy = idxmalloc(20*(*nn), "METIS_MESHPARTNODAL: adjncy");
    
      METIS_MeshToNodal(ne, nn, elmnts, etype, &pnumflag, xadj, adjncy);
    
      adjncy = realloc(adjncy, xadj[*nn]*sizeof(idxtype));
    
      options[0] = 0;
      METIS_PartGraphKway(nn, xadj, adjncy, NULL, NULL, &wgtflag, &pnumflag, nparts, options, edgecut, npart);
    
      /* OK, now compute an element partition based on the nodal partition npart */
      idxset(*ne, -1, epart);
      pwgts = idxsmalloc(*nparts, 0, "METIS_MESHPARTNODAL: pwgts");
      for (i=0; i<*ne; i++) {
        me = npart[elmnts[i*esize]];
        for (j=1; j<esize; j++) {
          if (npart[elmnts[i*esize+j]] != me)
            break;
        }
        if (j == esize) {
          epart[i] = me;
          pwgts[me]++;
        }
      }
    
      maxpwgt = 1.03*(*ne)/(*nparts);
      for (i=0; i<*ne; i++) {
        if (epart[i] == -1) { /* Assign the boundary element */
          nnbrs = 0;
          for (j=0; j<esize; j++) {
            me = npart[elmnts[i*esize+j]];
            for (k=0; k<nnbrs; k++) {
              if (nbrind[k] == me) {
                nbrwgt[k]++;
                break;
              }
            }
            if (k == nnbrs) {
              nbrind[nnbrs] = me;
              nbrwgt[nnbrs++] = 1;
            }
          }
          /* Try to assign it first to the domain with most things in common */
          j = iamax(nnbrs, nbrwgt);
          if (pwgts[nbrind[j]] < maxpwgt) {
            epart[i] = nbrind[j];
          }
          else {
            /* If that fails, assign it to a light domain */
            for (j=0; j<nnbrs; j++) {
              if (pwgts[nbrind[j]] < maxpwgt) {
                epart[i] = nbrind[j];
                break;
              }
            }
            if (j == nnbrs) 
              epart[i] = nbrind[iamax(nnbrs, nbrwgt)];
          }
          pwgts[epart[i]]++;
        }
      }
    
      if (*numflag == 1)
        ChangeMesh2FNumbering2((*ne)*esize, elmnts, *ne, *nn, epart, npart);
    
      GKfree(&xadj, &adjncy, &pwgts, LTERM);
    
    }
    
    
    /*************************************************************************
    * This function partitions a finite element mesh by partitioning its dual
    * graph using KMETIS and then assigning nodes in a load balanced fashion.
    **************************************************************************/
    void METIS_PartMeshDual(int *ne, int *nn, idxtype *elmnts, int *etype, int *numflag, 
                            int *nparts, int *edgecut, idxtype *epart, idxtype *npart)
    {
      int i, j, k, me;
      idxtype *xadj, *adjncy, *pwgts, *nptr, *nind;
      int options[10], pnumflag=0, wgtflag=0;
      int nnbrs, nbrind[200], nbrwgt[200], maxpwgt;
      int esize, esizes[] = {-1, 3, 4, 8, 4};
    
      esize = esizes[*etype];
    
      if (*numflag == 1)
        ChangeMesh2CNumbering((*ne)*esize, elmnts);
    
      xadj = idxmalloc(*ne+1, "METIS_MESHPARTNODAL: xadj");
      adjncy = idxmalloc(esize*(*ne), "METIS_MESHPARTNODAL: adjncy");
    
      METIS_MeshToDual(ne, nn, elmnts, etype, &pnumflag, xadj, adjncy);
    
      options[0] = 0;
      METIS_PartGraphKway(ne, xadj, adjncy, NULL, NULL, &wgtflag, &pnumflag, nparts, options, edgecut, epart);
    
      /* Construct the node-element list */
      nptr = idxsmalloc(*nn+1, 0, "METIS_MESHPARTDUAL: nptr");
      for (j=esize*(*ne), i=0; i<j; i++) 
        nptr[elmnts[i]]++;
      MAKECSR(i, *nn, nptr);
    
      nind = idxmalloc(nptr[*nn], "METIS_MESHPARTDUAL: nind");
      for (k=i=0; i<(*ne); i++) {
        for (j=0; j<esize; j++, k++) 
          nind[nptr[elmnts[k]]++] = i;
      }
      for (i=(*nn); i>0; i--)
        nptr[i] = nptr[i-1];
      nptr[0] = 0;
    
    
      /* OK, now compute a nodal partition based on the element partition npart */
      idxset(*nn, -1, npart);
      pwgts = idxsmalloc(*nparts, 0, "METIS_MESHPARTDUAL: pwgts");
      for (i=0; i<*nn; i++) {
        me = epart[nind[nptr[i]]];
        for (j=nptr[i]+1; j<nptr[i+1]; j++) {
          if (epart[nind[j]] != me)
            break;
        }
        if (j == nptr[i+1]) {
          npart[i] = me;
          pwgts[me]++;
        }
      }
    
      maxpwgt = 1.03*(*nn)/(*nparts);
      for (i=0; i<*nn; i++) {
        if (npart[i] == -1) { /* Assign the boundary element */
          nnbrs = 0;
          for (j=nptr[i]; j<nptr[i+1]; j++) {
            me = epart[nind[j]];
            for (k=0; k<nnbrs; k++) {
              if (nbrind[k] == me) {
                nbrwgt[k]++;
                break;
              }
            }
            if (k == nnbrs) {
              nbrind[nnbrs] = me;
              nbrwgt[nnbrs++] = 1;
            }
          }
          /* Try to assign it first to the domain with most things in common */
          j = iamax(nnbrs, nbrwgt);
          if (pwgts[nbrind[j]] < maxpwgt) {
            npart[i] = nbrind[j];
          }
          else {
            /* If that fails, assign it to a light domain */
            npart[i] = nbrind[0];
            for (j=0; j<nnbrs; j++) {
              if (pwgts[nbrind[j]] < maxpwgt) {
                npart[i] = nbrind[j];
                break;
              }
            }
          }
          pwgts[npart[i]]++;
        }
      }
    
      if (*numflag == 1)
        ChangeMesh2FNumbering2((*ne)*esize, elmnts, *ne, *nn, epart, npart);
    
      GKfree(&xadj, &adjncy, &pwgts, &nptr, &nind, LTERM);
    
    }