Actual source code: amd.c

  1: #define PETSCMAT_DLL

 3:  #include petscmat.h
 4:  #include ../src/mat/order/order.h
  5: #define UF_long long long
  6: #define UF_long_max LONG_LONG_MAX
  7: #define UF_long_id "%lld"
  8: #include <amd.h>

 10: #if defined(PETSC_USE_64BIT_INDICES)
 11: #  define amd_AMD_defaults amd_l_defaults
 12: #  define amd_AMD_order    amd_l_order
 13: #else
 14: #  define amd_AMD_defaults amd_defaults
 15: #  define amd_AMD_order    amd_order
 16: #endif

 19: /*
 20:     MatOrdering_AMD - Find the Approximate Minimum Degree ordering

 22:     This provides an interface to Tim Davis' AMD package (used by UMFPACK, CHOLMOD, Matlab, etc).
 23: */
 26: PetscErrorCode  MatOrdering_AMD(Mat mat,const MatOrderingType type,IS *row,IS *col)
 27: {
 29:   PetscInt       nrow,*ia,*ja,*perm;
 30:   int            status;
 31:   PetscReal      val;
 32:   double         Control[AMD_CONTROL],Info[AMD_INFO];
 33:   PetscTruth     tval,done;

 36:   /*
 37:      AMD does not require that the matrix be symmetric (it does so internally,
 38:      at least in so far as computing orderings for A+A^T.
 39:   */
 40:   MatGetRowIJ(mat,0,PETSC_FALSE,PETSC_TRUE,&nrow,&ia,&ja,&done);
 41:   if (!done) SETERRQ1(PETSC_ERR_SUP,"Cannot get rows for matrix type %s",((PetscObject)mat)->type_name);

 43:   amd_AMD_defaults(Control);
 44:   PetscOptionsBegin(((PetscObject)mat)->comm,((PetscObject)mat)->prefix,"AMD Options","Mat");
 45:   /*
 46:     We have to use temporary values here because AMD always uses double, even though PetscReal may be single
 47:   */
 48:   val = (PetscReal)Control[AMD_DENSE];
 49:   PetscOptionsReal("-mat_ordering_amd_dense","threshold for \"dense\" rows/columns","None",val,&val,PETSC_NULL);
 50:   Control[AMD_DENSE] = (double)val;

 52:   tval = (PetscTruth)Control[AMD_AGGRESSIVE];
 53:   PetscOptionsTruth("-mat_ordering_amd_aggressive","use aggressive absorption","None",tval,&tval,PETSC_NULL);
 54:   Control[AMD_AGGRESSIVE] = (double)tval;
 55:   PetscOptionsEnd();

 57:   PetscMalloc(nrow*sizeof(PetscInt),&perm);
 58:   status = amd_AMD_order(nrow,ia,ja,perm,Control,Info);
 59:   switch (status) {
 60:     case AMD_OK: break;
 61:     case AMD_OK_BUT_JUMBLED:
 62:       /* The result is fine, but PETSc matrices are supposed to satisfy stricter preconditions, so PETSc considers a
 63:       * matrix that triggers this error condition to be invalid.
 64:       */
 65:       SETERRQ(PETSC_ERR_PLIB,"According to AMD, the matrix has unsorted and/or duplicate row indices");
 66:     case AMD_INVALID:
 67:       amd_info(Info);
 68:       SETERRQ(PETSC_ERR_PLIB,"According to AMD, the matrix is invalid");
 69:     case AMD_OUT_OF_MEMORY:
 70:       SETERRQ(PETSC_ERR_MEM,"AMD could not compute ordering");
 71:     default:
 72:       SETERRQ(PETSC_ERR_LIB,"Unexpected return value");
 73:   }
 74:   MatRestoreRowIJ(mat,0,PETSC_FALSE,PETSC_TRUE,&nrow,&ia,&ja,&done);

 76:   ISCreateGeneral(PETSC_COMM_SELF,nrow,perm,row);
 77:   ISCreateGeneral(PETSC_COMM_SELF,nrow,perm,col);
 78:   PetscFree(perm);
 79:   return(0);
 80: }