Actual source code: packm.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      2: #include <../src/dm/impls/composite/packimpl.h>       /*I  "petscdmcomposite.h"  I*/

      6: static PetscErrorCode DMCreateMatrix_Composite_Nest(DM dm,Mat *J)
      7: {
      8:   const DM_Composite           *com = (DM_Composite*)dm->data;
      9:   const struct DMCompositeLink *rlink,*clink;
     10:   PetscErrorCode               ierr;
     11:   IS                           *isg;
     12:   Mat                          *submats;
     13:   PetscInt                     i,j,n;

     16:   n = com->nDM;                 /* Total number of entries */

     18:   /* Explicit index sets are not required for MatCreateNest, but getting them here allows MatNest to do consistency
     19:    * checking and allows ISEqual to compare by identity instead of by contents. */
     20:   DMCompositeGetGlobalISs(dm,&isg);

     22:   /* Get submatrices */
     23:   PetscMalloc1(n*n,&submats);
     24:   for (i=0,rlink=com->next; rlink; i++,rlink=rlink->next) {
     25:     for (j=0,clink=com->next; clink; j++,clink=clink->next) {
     26:       Mat sub = NULL;
     27:       if (i == j) {
     28:         DMCreateMatrix(rlink->dm,&sub);
     29:       } else if (com->FormCoupleLocations) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot manage off-diagonal parts yet");
     30:       submats[i*n+j] = sub;
     31:     }
     32:   }

     34:   MatCreateNest(PetscObjectComm((PetscObject)dm),n,isg,n,isg,submats,J);

     36:   /* Disown references */
     37:   for (i=0; i<n; i++) {ISDestroy(&isg[i]);}
     38:   PetscFree(isg);

     40:   for (i=0; i<n*n; i++) {
     41:     if (submats[i]) {MatDestroy(&submats[i]);}
     42:   }
     43:   PetscFree(submats);
     44:   return(0);
     45: }

     49: static PetscErrorCode DMCreateMatrix_Composite_AIJ(DM dm,Mat *J)
     50: {
     51:   PetscErrorCode         ierr;
     52:   DM_Composite           *com = (DM_Composite*)dm->data;
     53:   struct DMCompositeLink *next;
     54:   PetscInt               m,*dnz,*onz,i,j,mA;
     55:   Mat                    Atmp;
     56:   PetscMPIInt            rank;
     57:   PetscBool              dense = PETSC_FALSE;

     60:   /* use global vector to determine layout needed for matrix */
     61:   m = com->n;

     63:   MatCreate(PetscObjectComm((PetscObject)dm),J);
     64:   MatSetSizes(*J,m,m,PETSC_DETERMINE,PETSC_DETERMINE);
     65:   MatSetType(*J,dm->mattype);

     67:   /*
     68:      Extremely inefficient but will compute entire Jacobian for testing
     69:   */
     70:   PetscOptionsGetBool(((PetscObject)dm)->options,((PetscObject)dm)->prefix,"-dmcomposite_dense_jacobian",&dense,NULL);
     71:   if (dense) {
     72:     PetscInt    rstart,rend,*indices;
     73:     PetscScalar *values;

     75:     mA   = com->N;
     76:     MatMPIAIJSetPreallocation(*J,mA,NULL,mA-m,NULL);
     77:     MatSeqAIJSetPreallocation(*J,mA,NULL);

     79:     MatGetOwnershipRange(*J,&rstart,&rend);
     80:     PetscMalloc2(mA,&values,mA,&indices);
     81:     PetscMemzero(values,mA*sizeof(PetscScalar));
     82:     for (i=0; i<mA; i++) indices[i] = i;
     83:     for (i=rstart; i<rend; i++) {
     84:       MatSetValues(*J,1,&i,mA,indices,values,INSERT_VALUES);
     85:     }
     86:     PetscFree2(values,indices);
     87:     MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
     88:     MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
     89:     return(0);
     90:   }

     92:   MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);
     93:   MatPreallocateInitialize(PetscObjectComm((PetscObject)dm),m,m,dnz,onz);
     94:   /* loop over packed objects, handling one at at time */
     95:   next = com->next;
     96:   while (next) {
     97:     PetscInt       nc,rstart,*ccols,maxnc;
     98:     const PetscInt *cols,*rstarts;
     99:     PetscMPIInt    proc;

    101:     DMCreateMatrix(next->dm,&Atmp);
    102:     MatGetOwnershipRange(Atmp,&rstart,NULL);
    103:     MatGetOwnershipRanges(Atmp,&rstarts);
    104:     MatGetLocalSize(Atmp,&mA,NULL);

    106:     maxnc = 0;
    107:     for (i=0; i<mA; i++) {
    108:       MatGetRow(Atmp,rstart+i,&nc,NULL,NULL);
    109:       MatRestoreRow(Atmp,rstart+i,NULL,NULL,NULL);
    110:       maxnc = PetscMax(nc,maxnc);
    111:     }
    112:     PetscMalloc1(maxnc,&ccols);
    113:     for (i=0; i<mA; i++) {
    114:       MatGetRow(Atmp,rstart+i,&nc,&cols,NULL);
    115:       /* remap the columns taking into how much they are shifted on each process */
    116:       for (j=0; j<nc; j++) {
    117:         proc = 0;
    118:         while (cols[j] >= rstarts[proc+1]) proc++;
    119:         ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc];
    120:       }
    121:       MatPreallocateSet(com->rstart+next->rstart+i,nc,ccols,dnz,onz);
    122:       MatRestoreRow(Atmp,rstart+i,&nc,&cols,NULL);
    123:     }
    124:     PetscFree(ccols);
    125:     MatDestroy(&Atmp);
    126:     next = next->next;
    127:   }
    128:   if (com->FormCoupleLocations) {
    129:     (*com->FormCoupleLocations)(dm,NULL,dnz,onz,__rstart,__nrows,__start,__end);
    130:   }
    131:   MatMPIAIJSetPreallocation(*J,0,dnz,0,onz);
    132:   MatSeqAIJSetPreallocation(*J,0,dnz);
    133:   MatPreallocateFinalize(dnz,onz);

    135:   if (dm->prealloc_only) return(0);

    137:   next = com->next;
    138:   while (next) {
    139:     PetscInt          nc,rstart,row,maxnc,*ccols;
    140:     const PetscInt    *cols,*rstarts;
    141:     const PetscScalar *values;
    142:     PetscMPIInt       proc;

    144:     DMCreateMatrix(next->dm,&Atmp);
    145:     MatGetOwnershipRange(Atmp,&rstart,NULL);
    146:     MatGetOwnershipRanges(Atmp,&rstarts);
    147:     MatGetLocalSize(Atmp,&mA,NULL);
    148:     maxnc = 0;
    149:     for (i=0; i<mA; i++) {
    150:       MatGetRow(Atmp,rstart+i,&nc,NULL,NULL);
    151:       maxnc = PetscMax(nc,maxnc);
    152:       MatRestoreRow(Atmp,rstart+i,&nc,NULL,NULL);
    153:     }
    154:     PetscMalloc1(maxnc,&ccols);
    155:     for (i=0; i<mA; i++) {
    156:       MatGetRow(Atmp,rstart+i,&nc,(const PetscInt**)&cols,&values);
    157:       for (j=0; j<nc; j++) {
    158:         proc = 0;
    159:         while (cols[j] >= rstarts[proc+1]) proc++;
    160:         ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc];
    161:       }
    162:       row  = com->rstart+next->rstart+i;
    163:       MatSetValues(*J,1,&row,nc,ccols,values,INSERT_VALUES);
    164:       MatRestoreRow(Atmp,rstart+i,&nc,(const PetscInt**)&cols,&values);
    165:     }
    166:     PetscFree(ccols);
    167:     MatDestroy(&Atmp);
    168:     next = next->next;
    169:   }
    170:   if (com->FormCoupleLocations) {
    171:     PetscInt __rstart;
    172:     MatGetOwnershipRange(*J,&__rstart,NULL);
    173:     (*com->FormCoupleLocations)(dm,*J,NULL,NULL,__rstart,0,0,0);
    174:   }
    175:   MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
    176:   MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
    177:   return(0);
    178: }

    182: PetscErrorCode DMCreateMatrix_Composite(DM dm,Mat *J)
    183: {
    184:   PetscErrorCode         ierr;
    185:   PetscBool              usenest;
    186:   ISLocalToGlobalMapping ltogmap;

    189:   DMSetUp(dm);
    190:   PetscStrcmp(dm->mattype,MATNEST,&usenest);
    191:   if (usenest) {
    192:     DMCreateMatrix_Composite_Nest(dm,J);
    193:   } else {
    194:     DMCreateMatrix_Composite_AIJ(dm,J);
    195:   }

    197:   DMGetLocalToGlobalMapping(dm,&ltogmap);
    198:   MatSetLocalToGlobalMapping(*J,ltogmap,ltogmap);
    199:   return(0);
    200: }