Actual source code: freespace.c

      1: #include <../src/mat/utils/freespace.h>

      3: PetscErrorCode PetscFreeSpaceGet(PetscInt n, PetscFreeSpaceList *list)
      4: {
      5:   PetscFreeSpaceList a;

      7:   PetscFunctionBegin;
      8:   PetscCall(PetscNew(&a));
      9:   PetscCall(PetscMalloc1(n, &a->array_head));

     11:   a->array            = a->array_head;
     12:   a->local_remaining  = n;
     13:   a->local_used       = 0;
     14:   a->total_array_size = 0;
     15:   a->more_space       = NULL;

     17:   if (*list) {
     18:     (*list)->more_space = a;
     19:     a->total_array_size = (*list)->total_array_size;
     20:   }

     22:   a->total_array_size += n;
     23:   *list = a;
     24:   PetscFunctionReturn(PETSC_SUCCESS);
     25: }

     27: PetscErrorCode PetscFreeSpaceContiguous(PetscFreeSpaceList *head, PetscInt *space)
     28: {
     29:   PetscFreeSpaceList a;

     31:   PetscFunctionBegin;
     32:   while (*head) {
     33:     a = (*head)->more_space;
     34:     PetscCall(PetscArraycpy(space, (*head)->array_head, (*head)->local_used));
     35:     space = PetscSafePointerPlusOffset(space, (*head)->local_used);
     36:     PetscCall(PetscFree((*head)->array_head));
     37:     PetscCall(PetscFree(*head));
     38:     *head = a;
     39:   }
     40:   PetscFunctionReturn(PETSC_SUCCESS);
     41: }

     43: /*
     44:   PetscFreeSpaceContiguous_LU -
     45:     Copy a linket list obtained from matrix symbolic ILU or LU factorization into a contiguous array
     46:   that enables an efficient matrix triangular solve.

     48:    Input Parameters:
     49: +  head - linked list of column indices obtained from matrix symbolic ILU or LU factorization
     50: .  space - an allocated array with length nnz of factored matrix.
     51: .  n - order of the matrix
     52: .  bi - row pointer of factored matrix L with length n+1.
     53: -  bdiag - array of length n+1. bdiag[i] points to diagonal of U(i,:), and bdiag[n] points to entry of U(n-1,0)-1.

     55:    Output Parameter:
     56: .  space - column indices are copied into this array with contiguous layout of L and U

     58:    See MatILUFactorSymbolic_SeqAIJ_ilu0() for detailed data structure of L and U
     59: */
     60: PetscErrorCode PetscFreeSpaceContiguous_LU(PetscFreeSpaceList *head, PetscInt *space, PetscInt n, PetscInt *bi, PetscInt *bdiag)
     61: {
     62:   PetscFreeSpaceList a;
     63:   PetscInt           row, nnz, *bj, *array, total, bi_temp;
     64:   PetscInt           nnzL, nnzU;

     66:   PetscFunctionBegin;
     67:   bi_temp = bi[n];
     68:   row     = 0;
     69:   total   = 0;
     70:   nnzL    = bdiag[0];
     71:   while (*head) {
     72:     total += (*head)->local_used;
     73:     array = (*head)->array_head;

     75:     while (row < n) {
     76:       if (bi[row + 1] > total) break;
     77:       /* copy array entries into bj for this row */
     78:       nnz = bi[row + 1] - bi[row];
     79:       /* set bi[row] for new datastruct */
     80:       if (row == 0) {
     81:         bi[row] = 0;
     82:       } else {
     83:         bi[row] = bi[row - 1] + nnzL; /* nnzL of previous row */
     84:       }

     86:       /* L part */
     87:       nnzL = bdiag[row];
     88:       bj   = space + bi[row];
     89:       PetscCall(PetscArraycpy(bj, array, nnzL));

     91:       /* diagonal entry */
     92:       bdiag[row]        = bi_temp - 1;
     93:       space[bdiag[row]] = row;

     95:       /* U part */
     96:       nnzU    = nnz - nnzL;
     97:       bi_temp = bi_temp - nnzU;
     98:       nnzU--; /* exclude diagonal */
     99:       bj = space + bi_temp;
    100:       PetscCall(PetscArraycpy(bj, array + nnzL + 1, nnzU));
    101:       array += nnz;
    102:       row++;
    103:     }

    105:     a = (*head)->more_space;
    106:     PetscCall(PetscFree((*head)->array_head));
    107:     PetscCall(PetscFree(*head));
    108:     *head = a;
    109:   }
    110:   if (n) {
    111:     bi[n]    = bi[n - 1] + nnzL;
    112:     bdiag[n] = bdiag[n - 1] - 1;
    113:   }
    114:   PetscFunctionReturn(PETSC_SUCCESS);
    115: }

    117: /*
    118:   PetscFreeSpaceContiguous_Cholesky -
    119:     Copy a linket list obtained from matrix symbolic ICC or Cholesky factorization into a contiguous array
    120:   that enables an efficient matrix triangular solve.

    122:    Input Parameters:
    123: +  head - linked list of column indices obtained from matrix symbolic ICC or Cholesky factorization
    124: .  space - an allocated array with length nnz of factored matrix.
    125: .  n - order of the matrix
    126: .  ui - row pointer of factored matrix with length n+1. All entries are set based on the traditional layout U matrix.
    127: -  udiag - array of length n.

    129:    Output Parameter:
    130: +  space - column indices are copied into this array with contiguous layout of U, with diagonal located as the last entry in each row
    131: -  udiag - indices of diagonal entries

    133:    See MatICCFactorSymbolic_SeqAIJ_newdatastruct() for detailed description.
    134: */

    136: PetscErrorCode PetscFreeSpaceContiguous_Cholesky(PetscFreeSpaceList *head, PetscInt *space, PetscInt n, PetscInt *ui, PetscInt *udiag)
    137: {
    138:   PetscFreeSpaceList a;
    139:   PetscInt           row, nnz, *uj, *array, total;

    141:   PetscFunctionBegin;
    142:   row   = 0;
    143:   total = 0;
    144:   while (*head) {
    145:     total += (*head)->local_used;
    146:     array = (*head)->array_head;

    148:     while (row < n) {
    149:       if (ui[row + 1] > total) break;
    150:       udiag[row] = ui[row + 1] - 1;           /* points to the last entry of U(row,:) */
    151:       nnz        = ui[row + 1] - ui[row] - 1; /* exclude diagonal */
    152:       uj         = space + ui[row];
    153:       PetscCall(PetscArraycpy(uj, array + 1, nnz));
    154:       uj[nnz] = array[0]; /* diagonal */
    155:       array += nnz + 1;
    156:       row++;
    157:     }

    159:     a = (*head)->more_space;
    160:     PetscCall(PetscFree((*head)->array_head));
    161:     PetscCall(PetscFree(*head));
    162:     *head = a;
    163:   }
    164:   PetscFunctionReturn(PETSC_SUCCESS);
    165: }

    167: PetscErrorCode PetscFreeSpaceDestroy(PetscFreeSpaceList head)
    168: {
    169:   PetscFreeSpaceList a;

    171:   PetscFunctionBegin;
    172:   while (head) {
    173:     a = (head)->more_space;
    174:     PetscCall(PetscFree((head)->array_head));
    175:     PetscCall(PetscFree(head));
    176:     head = a;
    177:   }
    178:   PetscFunctionReturn(PETSC_SUCCESS);
    179: }