Actual source code: amd.c
2: #include <petscmat.h>
3: #include <petsc/private/matorderimpl.h>
4: #include <amd.h>
6: #if defined(PETSC_USE_64BIT_INDICES)
7: #define amd_AMD_defaults amd_l_defaults
8: /* the type casts are needed because PetscInt is long long while SuiteSparse_long is long and compilers warn even when they are identical */
9: #define amd_AMD_order(a, b, c, d, e, f) amd_l_order((SuiteSparse_long)a, (SuiteSparse_long *)b, (SuiteSparse_long *)c, (SuiteSparse_long *)d, e, f)
10: #else
11: #define amd_AMD_defaults amd_defaults
12: #define amd_AMD_order amd_order
13: #endif
15: /*
16: MatGetOrdering_AMD - Find the Approximate Minimum Degree ordering
18: This provides an interface to Tim Davis' AMD package (used by UMFPACK, CHOLMOD, MATLAB, etc).
19: */
20: PETSC_INTERN PetscErrorCode MatGetOrdering_AMD(Mat mat, MatOrderingType type, IS *row, IS *col)
21: {
22: PetscInt nrow, *perm;
23: const PetscInt *ia, *ja;
24: int status;
25: PetscReal val;
26: double Control[AMD_CONTROL], Info[AMD_INFO];
27: PetscBool tval, done;
29: /*
30: AMD does not require that the matrix be symmetric (it does so internally,
31: at least in so far as computing orderings for A+A^T.
32: */
33: MatGetRowIJ(mat, 0, PETSC_FALSE, PETSC_TRUE, &nrow, &ia, &ja, &done);
36: amd_AMD_defaults(Control);
37: PetscOptionsBegin(PetscObjectComm((PetscObject)mat), ((PetscObject)mat)->prefix, "AMD Options", "Mat");
38: /*
39: We have to use temporary values here because AMD always uses double, even though PetscReal may be single
40: */
41: val = (PetscReal)Control[AMD_DENSE];
42: PetscOptionsReal("-mat_ordering_amd_dense", "threshold for \"dense\" rows/columns", "None", val, &val, NULL);
43: Control[AMD_DENSE] = (double)val;
45: tval = (PetscBool)Control[AMD_AGGRESSIVE];
46: PetscOptionsBool("-mat_ordering_amd_aggressive", "use aggressive absorption", "None", tval, &tval, NULL);
47: Control[AMD_AGGRESSIVE] = (double)tval;
49: PetscOptionsEnd();
51: PetscMalloc1(nrow, &perm);
52: status = amd_AMD_order(nrow, ia, ja, perm, Control, Info);
53: switch (status) {
54: case AMD_OK:
55: break;
56: case AMD_OK_BUT_JUMBLED:
57: /* The result is fine, but PETSc matrices are supposed to satisfy stricter preconditions, so PETSc considers a
58: * matrix that triggers this error condition to be invalid.
59: */
60: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "According to AMD, the matrix has unsorted and/or duplicate row indices");
61: case AMD_INVALID:
62: amd_info(Info);
63: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "According to AMD, the matrix is invalid");
64: case AMD_OUT_OF_MEMORY:
65: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MEM, "AMD could not compute ordering");
66: default:
67: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_LIB, "Unexpected return value");
68: }
69: MatRestoreRowIJ(mat, 0, PETSC_FALSE, PETSC_TRUE, NULL, &ia, &ja, &done);
71: ISCreateGeneral(PETSC_COMM_SELF, nrow, perm, PETSC_COPY_VALUES, row);
72: ISCreateGeneral(PETSC_COMM_SELF, nrow, perm, PETSC_OWN_POINTER, col);
73: return 0;
74: }