1*14277c92SJacob Faibussowitsch static const char help[] = "Tests MatGetDiagonal().\n\n"; 2*14277c92SJacob Faibussowitsch 3*14277c92SJacob Faibussowitsch #include <petscmat.h> 4*14277c92SJacob Faibussowitsch 5*14277c92SJacob Faibussowitsch static PetscErrorCode CheckDiagonal(Mat A, Vec diag, PetscScalar dval) 6*14277c92SJacob Faibussowitsch { 7*14277c92SJacob Faibussowitsch static PetscBool first_time = PETSC_TRUE; 8*14277c92SJacob Faibussowitsch const PetscReal rtol = 1e-10, atol = PETSC_SMALL; 9*14277c92SJacob Faibussowitsch PetscInt rstart, rend, n; 10*14277c92SJacob Faibussowitsch const PetscScalar *arr; 11*14277c92SJacob Faibussowitsch 12*14277c92SJacob Faibussowitsch PetscFunctionBegin; 13*14277c92SJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 14*14277c92SJacob Faibussowitsch // If matrix is AIJ, MatSetRandom() will have randomly choosen the locations of nonzeros, 15*14277c92SJacob Faibussowitsch // which may not be on the diagonal. So a reallocation is not necessarily a bad thing here. 16*14277c92SJacob Faibussowitsch if (first_time) PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 17*14277c92SJacob Faibussowitsch for (PetscInt i = rstart; i < rend; ++i) PetscCall(MatSetValue(A, i, i, dval, INSERT_VALUES)); 18*14277c92SJacob Faibussowitsch if (first_time) { 19*14277c92SJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 20*14277c92SJacob Faibussowitsch first_time = PETSC_FALSE; 21*14277c92SJacob Faibussowitsch } 22*14277c92SJacob Faibussowitsch 23*14277c92SJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 24*14277c92SJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 25*14277c92SJacob Faibussowitsch PetscCall(MatViewFromOptions(A, NULL, "-mat_view_assembled")); 26*14277c92SJacob Faibussowitsch 27*14277c92SJacob Faibussowitsch PetscCall(VecSetRandom(diag, NULL)); 28*14277c92SJacob Faibussowitsch PetscCall(MatGetDiagonal(A, diag)); 29*14277c92SJacob Faibussowitsch PetscCall(VecViewFromOptions(diag, NULL, "-diag_vec_view")); 30*14277c92SJacob Faibussowitsch 31*14277c92SJacob Faibussowitsch PetscCall(VecGetLocalSize(diag, &n)); 32*14277c92SJacob Faibussowitsch PetscCall(VecGetArrayRead(diag, &arr)); 33*14277c92SJacob Faibussowitsch for (PetscInt i = 0; i < n; ++i) { 34*14277c92SJacob Faibussowitsch const PetscScalar lhs = arr[i]; 35*14277c92SJacob Faibussowitsch 36*14277c92SJacob Faibussowitsch if (!PetscIsCloseAtTolScalar(lhs, dval, rtol, atol)) { 37*14277c92SJacob Faibussowitsch const PetscReal lhs_r = PetscRealPart(lhs); 38*14277c92SJacob Faibussowitsch const PetscReal lhs_i = PetscImaginaryPart(lhs); 39*14277c92SJacob Faibussowitsch const PetscReal dval_r = PetscRealPart(dval); 40*14277c92SJacob Faibussowitsch const PetscReal dval_i = PetscImaginaryPart(dval); 41*14277c92SJacob Faibussowitsch 42*14277c92SJacob Faibussowitsch PetscCheck(PetscIsCloseAtTol(lhs_r, dval_r, rtol, atol), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Real component actual[%" PetscInt_FMT "] %g != expected[%" PetscInt_FMT "] %g", i, (double)lhs_r, i, (double)dval_r); 43*14277c92SJacob Faibussowitsch PetscCheck(PetscIsCloseAtTol(lhs_i, dval_i, rtol, atol), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Imaginary component actual[%" PetscInt_FMT "] %g != expected[%" PetscInt_FMT "] %g", i, (double)lhs_i, i, (double)dval_i); 44*14277c92SJacob Faibussowitsch } 45*14277c92SJacob Faibussowitsch } 46*14277c92SJacob Faibussowitsch PetscCall(VecRestoreArrayRead(diag, &arr)); 47*14277c92SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48*14277c92SJacob Faibussowitsch } 49*14277c92SJacob Faibussowitsch 50*14277c92SJacob Faibussowitsch static PetscErrorCode InitializeMatrix(Mat A) 51*14277c92SJacob Faibussowitsch { 52*14277c92SJacob Faibussowitsch MatType mtype; 53*14277c92SJacob Faibussowitsch char *tmp; 54*14277c92SJacob Faibussowitsch 55*14277c92SJacob Faibussowitsch PetscFunctionBegin; 56*14277c92SJacob Faibussowitsch PetscCall(MatSetUp(A)); 57*14277c92SJacob Faibussowitsch PetscCall(MatGetType(A, &mtype)); 58*14277c92SJacob Faibussowitsch PetscCall(PetscStrstr(mtype, "aij", &tmp)); 59*14277c92SJacob Faibussowitsch if (tmp) { 60*14277c92SJacob Faibussowitsch PetscInt rows, cols, diag_nnz, offdiag_nnz; 61*14277c92SJacob Faibussowitsch PetscInt *dnnz, *onnz; 62*14277c92SJacob Faibussowitsch 63*14277c92SJacob Faibussowitsch // is some kind of AIJ 64*14277c92SJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &rows, &cols)); 65*14277c92SJacob Faibussowitsch // at least 3 nonzeros in diagonal block 66*14277c92SJacob Faibussowitsch diag_nnz = PetscMin(cols, 3); 67*14277c92SJacob Faibussowitsch // leave at least 3 *zeros* per row 68*14277c92SJacob Faibussowitsch offdiag_nnz = PetscMax(cols - diag_nnz - 3, 0); 69*14277c92SJacob Faibussowitsch PetscCall(PetscMalloc2(rows, &dnnz, rows, &onnz)); 70*14277c92SJacob Faibussowitsch for (PetscInt i = 0; i < rows; ++i) { 71*14277c92SJacob Faibussowitsch dnnz[i] = diag_nnz; 72*14277c92SJacob Faibussowitsch onnz[i] = offdiag_nnz; 73*14277c92SJacob Faibussowitsch } 74*14277c92SJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(A, PETSC_DECIDE, dnnz, onnz, NULL, NULL)); 75*14277c92SJacob Faibussowitsch PetscCall(PetscFree2(dnnz, onnz)); 76*14277c92SJacob Faibussowitsch } 77*14277c92SJacob Faibussowitsch 78*14277c92SJacob Faibussowitsch PetscCall(MatSetRandom(A, NULL)); 79*14277c92SJacob Faibussowitsch PetscCall(MatViewFromOptions(A, NULL, "-mat_view_setup")); 80*14277c92SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81*14277c92SJacob Faibussowitsch } 82*14277c92SJacob Faibussowitsch 83*14277c92SJacob Faibussowitsch int main(int argc, char **argv) 84*14277c92SJacob Faibussowitsch { 85*14277c92SJacob Faibussowitsch Mat A; 86*14277c92SJacob Faibussowitsch Vec diag; 87*14277c92SJacob Faibussowitsch 88*14277c92SJacob Faibussowitsch PetscFunctionBeginUser; 89*14277c92SJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 90*14277c92SJacob Faibussowitsch 91*14277c92SJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &A)); 92*14277c92SJacob Faibussowitsch PetscCall(MatSetSizes(A, 10, 10, PETSC_DECIDE, PETSC_DECIDE)); 93*14277c92SJacob Faibussowitsch PetscCall(MatSetFromOptions(A)); 94*14277c92SJacob Faibussowitsch 95*14277c92SJacob Faibussowitsch PetscCall(InitializeMatrix(A)); 96*14277c92SJacob Faibussowitsch 97*14277c92SJacob Faibussowitsch PetscCall(MatCreateVecs(A, &diag, NULL)); 98*14277c92SJacob Faibussowitsch 99*14277c92SJacob Faibussowitsch PetscCall(CheckDiagonal(A, diag, 0.0)); 100*14277c92SJacob Faibussowitsch PetscCall(CheckDiagonal(A, diag, 1.0)); 101*14277c92SJacob Faibussowitsch PetscCall(CheckDiagonal(A, diag, 2.0)); 102*14277c92SJacob Faibussowitsch 103*14277c92SJacob Faibussowitsch PetscCall(VecDestroy(&diag)); 104*14277c92SJacob Faibussowitsch PetscCall(MatDestroy(&A)); 105*14277c92SJacob Faibussowitsch PetscCall(PetscFinalize()); 106*14277c92SJacob Faibussowitsch return 0; 107*14277c92SJacob Faibussowitsch } 108*14277c92SJacob Faibussowitsch 109*14277c92SJacob Faibussowitsch /*TEST 110*14277c92SJacob Faibussowitsch 111*14277c92SJacob Faibussowitsch testset: 112*14277c92SJacob Faibussowitsch output_file: ./output/empty.out 113*14277c92SJacob Faibussowitsch nsize: {{1 2}} 114*14277c92SJacob Faibussowitsch suffix: dense 115*14277c92SJacob Faibussowitsch test: 116*14277c92SJacob Faibussowitsch suffix: standard 117*14277c92SJacob Faibussowitsch args: -mat_type dense 118*14277c92SJacob Faibussowitsch test: 119*14277c92SJacob Faibussowitsch suffix: cuda 120*14277c92SJacob Faibussowitsch requires: cuda 121*14277c92SJacob Faibussowitsch args: -mat_type densecuda 122*14277c92SJacob Faibussowitsch test: 123*14277c92SJacob Faibussowitsch suffix: hip 124*14277c92SJacob Faibussowitsch requires: hip 125*14277c92SJacob Faibussowitsch args: -mat_type densehip 126*14277c92SJacob Faibussowitsch 127*14277c92SJacob Faibussowitsch testset: 128*14277c92SJacob Faibussowitsch output_file: ./output/empty.out 129*14277c92SJacob Faibussowitsch nsize: {{1 2}} 130*14277c92SJacob Faibussowitsch suffix: aij 131*14277c92SJacob Faibussowitsch test: 132*14277c92SJacob Faibussowitsch suffix: standard 133*14277c92SJacob Faibussowitsch args: -mat_type aij 134*14277c92SJacob Faibussowitsch test: 135*14277c92SJacob Faibussowitsch suffix: cuda 136*14277c92SJacob Faibussowitsch requires: cuda 137*14277c92SJacob Faibussowitsch args: -mat_type aijcusparse 138*14277c92SJacob Faibussowitsch test: 139*14277c92SJacob Faibussowitsch suffix: hip 140*14277c92SJacob Faibussowitsch requires: hip 141*14277c92SJacob Faibussowitsch args: -mat_type aijhipsparse 142*14277c92SJacob Faibussowitsch test: 143*14277c92SJacob Faibussowitsch suffix: kokkos 144*14277c92SJacob Faibussowitsch requires: kokkos, kokkos_kernels 145*14277c92SJacob Faibussowitsch args: -mat_type aijkokkos 146*14277c92SJacob Faibussowitsch 147*14277c92SJacob Faibussowitsch TEST*/ 148