static PetscErrorCode PCSetUp_SPAI(PC pc) { PC_SPAI *ispai = (PC_SPAI*)pc->data; PetscErrorCode ierr; Mat AT; PetscFunctionBegin; init_SPAI(); if (ispai->sp) { ierr = ConvertMatToMatrix(ispai->comm_spai,pc->pmat,pc->pmat,&ispai->B);CHKERRQ(ierr); } else { /* Use the transpose to get the column nonzero structure. */ ierr = MatTranspose(pc->pmat,MAT_INITIAL_MATRIX,&AT);CHKERRQ(ierr); ierr = ConvertMatToMatrix(ispai->comm_spai,pc->pmat,AT,&ispai->B);CHKERRQ(ierr); ierr = MatDestroy(&AT);CHKERRQ(ierr); } /* Destroy the transpose */ /* Don't know how to do it. PETSc developers? */ /* construct SPAI preconditioner */ /* FILE *messages */ /* file for warning messages */ /* double epsilon */ /* tolerance */ /* int nbsteps */ /* max number of "improvement" steps per line */ /* int max */ /* max dimensions of is_I, q, etc. */ /* int maxnew */ /* max number of new entries per step */ /* int block_size */ /* block_size == 1 specifies scalar elments block_size == n specifies nxn constant-block elements block_size == 0 specifies variable-block elements */ /* int cache_size */ /* one of (1,2,3,4,5,6) indicting size of cache */ /* cache_size == 0 indicates no caching */ /* int verbose */ /* verbose == 0 specifies that SPAI is silent verbose == 1 prints timing and matrix statistics */ ierr = bspai(ispai->B,&ispai->M, stdout, ispai->epsilon, ispai->nbsteps, ispai->max, ispai->maxnew, ispai->block_size, ispai->cache_size, ispai->verbose);CHKERRQ(ierr); ierr = ConvertMatrixToMat(((PetscObject)pc)->comm,ispai->M,&ispai->PM);CHKERRQ(ierr); /* free the SPAI matrices */ sp_free_matrix(ispai->B); sp_free_matrix(ispai->M); PetscFunctionReturn(0); }
int bspai (matrix *A, matrix **bspai_matrix, FILE *messages_arg, /* file for warning messages */ double epsilon_arg, /* tolerance */ int nbsteps_arg, /* max number of accepted elements per line (sc = 0); is set to ld+lu+1 for spar = 2 */ int max_arg, /* max dimensions of I, q, etc. */ int maxnew_arg, /* max number of new entries per step */ int bs, /* block size */ int cache_size_arg, /* one of (1,2,3,4,5,6) indicting size of cache */ /* cache_size == 0 indicates no caching */ int verbose_arg, int spar_arg, int lower_diag_arg, int upper_diag_arg, double tau_arg) { matrix *B; matrix *M_B; matrix *M; extern int A_max_block_size; int total_bad_cols; int j,nnz,ierr; if (verbose_arg) matrix_statistics(A,"A"); if (spar_arg && A->max_block_size > 1) /* MH: ??? */ { printf("Sorry, sc > 0 only supported for block size 1\n"); exit(1); } /* Scalar case */ if (bs == 1) { if (verbose_arg && (A->myid == 0)) printf("\nConstructing scalar SPAI matrix M from A\n"); if ((ierr = spai(A, &M, messages_arg, epsilon_arg, nbsteps_arg, max_arg, maxnew_arg, cache_size_arg, verbose_arg, spar_arg, lower_diag_arg, upper_diag_arg, tau_arg)) != 0) return ierr; #ifdef MPI MPI_Barrier(A->comm); #endif } /* Block case */ else { /* Convert A to either a constant or variable block matrix B. */ /* The 3rd argument can be used to set an upper limit on the block size. For now it's unused (i.e., zero). */ if (verbose_arg && (A->myid == 0)) printf("\nConstructing block matrix B from A\n"); B = block_matrix(A,bs,0,verbose_arg); if (verbose_arg) matrix_statistics(B,"B"); if (verbose_arg && (A->myid == 0)) printf("Constructing block SPAI matrix M_B from B\n"); if ((ierr = spai(B, &M_B, messages_arg, epsilon_arg, nbsteps_arg, max_arg, maxnew_arg, cache_size_arg, verbose_arg, spar_arg, lower_diag_arg, upper_diag_arg, tau_arg)) != 0) return ierr; #ifdef MPI MPI_Barrier(A->comm); #endif /* VE */ if (num_bad_cols) printf("SPAI: # bad columns = %d\n",num_bad_cols); if (verbose_arg) matrix_statistics(M_B,"M_B"); /* Convert M_B to scalar matrix. */ if (verbose_arg && (A->myid == 0)) printf("\nConstructing scalar SPAI matrix M from M_B\n"); M = scalar_matrix(M_B,verbose_arg); sp_free_matrix(B); sp_free_matrix(M_B); } if (verbose_arg) matrix_statistics(M,"M"); *bspai_matrix = M; return 0; }