1*345a4b08SToby Isaac const char help[] = "Test PCMatSetApplyOperation() and PCMatGetApplyOperation()"; 2*345a4b08SToby Isaac 3*345a4b08SToby Isaac #include <petscpc.h> 4*345a4b08SToby Isaac 5*345a4b08SToby Isaac static PetscErrorCode TestVecEquality(Vec x, Vec y) 6*345a4b08SToby Isaac { 7*345a4b08SToby Isaac Vec diff; 8*345a4b08SToby Isaac PetscReal err, scale; 9*345a4b08SToby Isaac 10*345a4b08SToby Isaac PetscFunctionBegin; 11*345a4b08SToby Isaac PetscCall(VecDuplicate(x, &diff)); 12*345a4b08SToby Isaac PetscCall(VecCopy(x, diff)); 13*345a4b08SToby Isaac PetscCall(VecAXPY(diff, -1.0, y)); 14*345a4b08SToby Isaac PetscCall(VecNorm(diff, NORM_INFINITY, &err)); 15*345a4b08SToby Isaac PetscCall(VecNorm(x, NORM_INFINITY, &scale)); 16*345a4b08SToby Isaac PetscCheck(err <= PETSC_SMALL * scale, PetscObjectComm((PetscObject)x), PETSC_ERR_PLIB, "PC operation does not match Mat operation"); 17*345a4b08SToby Isaac PetscCall(VecDestroy(&diff)); 18*345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 19*345a4b08SToby Isaac } 20*345a4b08SToby Isaac 21*345a4b08SToby Isaac static PetscErrorCode TestMatEquality(Mat x, Mat y) 22*345a4b08SToby Isaac { 23*345a4b08SToby Isaac Mat diff; 24*345a4b08SToby Isaac PetscReal err, scale; 25*345a4b08SToby Isaac PetscInt m, n; 26*345a4b08SToby Isaac 27*345a4b08SToby Isaac PetscFunctionBegin; 28*345a4b08SToby Isaac PetscCall(MatGetSize(x, &m, &n)); 29*345a4b08SToby Isaac PetscCall(MatDuplicate(x, MAT_COPY_VALUES, &diff)); 30*345a4b08SToby Isaac PetscCall(MatAXPY(diff, -1.0, y, SAME_NONZERO_PATTERN)); 31*345a4b08SToby Isaac PetscCall(MatNorm(diff, NORM_FROBENIUS, &err)); 32*345a4b08SToby Isaac PetscCall(MatNorm(x, NORM_FROBENIUS, &scale)); 33*345a4b08SToby Isaac PetscCheck(err < PETSC_SMALL * m * n * scale, PetscObjectComm((PetscObject)x), PETSC_ERR_PLIB, "PC operation does not match Mat operation"); 34*345a4b08SToby Isaac PetscCall(MatDestroy(&diff)); 35*345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 36*345a4b08SToby Isaac } 37*345a4b08SToby Isaac 38*345a4b08SToby Isaac // Test PCMat with a given operation versus a Matrix that encode the same operation relative to the original matrix 39*345a4b08SToby Isaac static PetscErrorCode TestPCMatVersusMat(PC pc, Mat A, PetscRandom rand, MatOperation op) 40*345a4b08SToby Isaac { 41*345a4b08SToby Isaac Vec b, x, x2; 42*345a4b08SToby Isaac Mat B, X, X2; 43*345a4b08SToby Isaac MatOperation op2; 44*345a4b08SToby Isaac 45*345a4b08SToby Isaac PetscFunctionBegin; 46*345a4b08SToby Isaac PetscCall(PCMatSetApplyOperation(pc, op)); 47*345a4b08SToby Isaac PetscCall(PCView(pc, PETSC_VIEWER_STDOUT_SELF)); 48*345a4b08SToby Isaac PetscCall(PCMatGetApplyOperation(pc, &op2)); 49*345a4b08SToby Isaac PetscCheck(op == op2, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Input and output MatOperation differ"); 50*345a4b08SToby Isaac 51*345a4b08SToby Isaac PetscCall(MatCreateVecs(A, &b, &x)); 52*345a4b08SToby Isaac PetscCall(VecDuplicate(x, &x2)); 53*345a4b08SToby Isaac PetscCall(VecSetRandom(b, rand)); 54*345a4b08SToby Isaac 55*345a4b08SToby Isaac PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B)); 56*345a4b08SToby Isaac PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &X2)); 57*345a4b08SToby Isaac PetscCall(MatSetRandom(B, rand)); 58*345a4b08SToby Isaac 59*345a4b08SToby Isaac PetscCall(MatMult(A, b, x)); 60*345a4b08SToby Isaac PetscCall(PCApply(pc, b, x2)); 61*345a4b08SToby Isaac PetscCall(TestVecEquality(x, x2)); 62*345a4b08SToby Isaac 63*345a4b08SToby Isaac PetscCall(MatMultTranspose(A, b, x)); 64*345a4b08SToby Isaac PetscCall(PCApplyTranspose(pc, b, x2)); 65*345a4b08SToby Isaac PetscCall(TestVecEquality(x, x2)); 66*345a4b08SToby Isaac 67*345a4b08SToby Isaac PetscCall(MatMatMult(A, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &X)); 68*345a4b08SToby Isaac PetscCall(PCMatApply(pc, B, X2)); 69*345a4b08SToby Isaac PetscCall(TestMatEquality(X, X2)); 70*345a4b08SToby Isaac 71*345a4b08SToby Isaac PetscCall(MatDestroy(&X2)); 72*345a4b08SToby Isaac PetscCall(MatDestroy(&X)); 73*345a4b08SToby Isaac PetscCall(MatDestroy(&B)); 74*345a4b08SToby Isaac PetscCall(VecDestroy(&x2)); 75*345a4b08SToby Isaac PetscCall(VecDestroy(&x)); 76*345a4b08SToby Isaac PetscCall(VecDestroy(&b)); 77*345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 78*345a4b08SToby Isaac } 79*345a4b08SToby Isaac 80*345a4b08SToby Isaac int main(int argc, char **argv) 81*345a4b08SToby Isaac { 82*345a4b08SToby Isaac PetscInt n = 10; 83*345a4b08SToby Isaac Mat A, AT, AH, II, Ainv, AinvT; 84*345a4b08SToby Isaac MPI_Comm comm; 85*345a4b08SToby Isaac PC pc; 86*345a4b08SToby Isaac PetscRandom rand; 87*345a4b08SToby Isaac 88*345a4b08SToby Isaac PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 89*345a4b08SToby Isaac comm = PETSC_COMM_SELF; 90*345a4b08SToby Isaac 91*345a4b08SToby Isaac PetscCall(PetscRandomCreate(comm, &rand)); 92*345a4b08SToby Isaac if (PetscDefined(USE_COMPLEX)) { 93*345a4b08SToby Isaac PetscScalar i = PetscSqrtScalar(-1.0); 94*345a4b08SToby Isaac PetscCall(PetscRandomSetInterval(rand, -1.0 - i, 1.0 + i)); 95*345a4b08SToby Isaac } else { 96*345a4b08SToby Isaac PetscCall(PetscRandomSetInterval(rand, -1.0, 1.0)); 97*345a4b08SToby Isaac } 98*345a4b08SToby Isaac 99*345a4b08SToby Isaac PetscCall(MatCreateSeqDense(comm, n, n, NULL, &A)); 100*345a4b08SToby Isaac PetscCall(MatSetRandom(A, rand)); 101*345a4b08SToby Isaac 102*345a4b08SToby Isaac PetscCall(PCCreate(comm, &pc)); 103*345a4b08SToby Isaac PetscCall(PCSetType(pc, PCMAT)); 104*345a4b08SToby Isaac PetscCall(PCSetOperators(pc, A, A)); 105*345a4b08SToby Isaac PetscCall(PCSetUp(pc)); 106*345a4b08SToby Isaac 107*345a4b08SToby Isaac MatOperation default_op; 108*345a4b08SToby Isaac PetscCall(PCMatGetApplyOperation(pc, &default_op)); 109*345a4b08SToby Isaac PetscCheck(default_op == MATOP_MULT, comm, PETSC_ERR_PLIB, "Default operation has changed"); 110*345a4b08SToby Isaac 111*345a4b08SToby Isaac // Test setting an invalid operation 112*345a4b08SToby Isaac PetscCall(PetscPushErrorHandler(PetscReturnErrorHandler, NULL)); 113*345a4b08SToby Isaac PetscErrorCode ierr = PCMatSetApplyOperation(pc, MATOP_SET_VALUES); 114*345a4b08SToby Isaac PetscCall(PetscPopErrorHandler()); 115*345a4b08SToby Isaac PetscCheck(ierr == PETSC_ERR_ARG_INCOMP, comm, PETSC_ERR_PLIB, "Wrong error message for unsupported MatOperation"); 116*345a4b08SToby Isaac 117*345a4b08SToby Isaac PetscCall(TestPCMatVersusMat(pc, A, rand, MATOP_MULT)); 118*345a4b08SToby Isaac 119*345a4b08SToby Isaac PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &AT)); 120*345a4b08SToby Isaac PetscCall(TestPCMatVersusMat(pc, AT, rand, MATOP_MULT_TRANSPOSE)); 121*345a4b08SToby Isaac 122*345a4b08SToby Isaac PetscCall(MatHermitianTranspose(A, MAT_INITIAL_MATRIX, &AH)); 123*345a4b08SToby Isaac PetscCall(TestPCMatVersusMat(pc, AH, rand, MATOP_MULT_HERMITIAN_TRANSPOSE)); 124*345a4b08SToby Isaac 125*345a4b08SToby Isaac PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &II)); 126*345a4b08SToby Isaac PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &Ainv)); 127*345a4b08SToby Isaac PetscCall(MatZeroEntries(II)); 128*345a4b08SToby Isaac PetscCall(MatShift(II, 1.0)); 129*345a4b08SToby Isaac PetscCall(MatLUFactor(A, NULL, NULL, NULL)); 130*345a4b08SToby Isaac PetscCall(MatMatSolve(A, II, Ainv)); 131*345a4b08SToby Isaac PetscCall(PCSetOperators(pc, A, A)); 132*345a4b08SToby Isaac PetscCall(TestPCMatVersusMat(pc, Ainv, rand, MATOP_SOLVE)); 133*345a4b08SToby Isaac 134*345a4b08SToby Isaac PetscCall(MatTranspose(Ainv, MAT_INITIAL_MATRIX, &AinvT)); 135*345a4b08SToby Isaac PetscCall(TestPCMatVersusMat(pc, AinvT, rand, MATOP_SOLVE_TRANSPOSE)); 136*345a4b08SToby Isaac 137*345a4b08SToby Isaac PetscCall(PCDestroy(&pc)); 138*345a4b08SToby Isaac PetscCall(MatDestroy(&AinvT)); 139*345a4b08SToby Isaac PetscCall(MatDestroy(&Ainv)); 140*345a4b08SToby Isaac PetscCall(MatDestroy(&II)); 141*345a4b08SToby Isaac PetscCall(MatDestroy(&AH)); 142*345a4b08SToby Isaac PetscCall(MatDestroy(&AT)); 143*345a4b08SToby Isaac PetscCall(MatDestroy(&A)); 144*345a4b08SToby Isaac PetscCall(PetscRandomDestroy(&rand)); 145*345a4b08SToby Isaac PetscCall(PetscFinalize()); 146*345a4b08SToby Isaac return 0; 147*345a4b08SToby Isaac } 148*345a4b08SToby Isaac 149*345a4b08SToby Isaac /*TEST 150*345a4b08SToby Isaac 151*345a4b08SToby Isaac test: 152*345a4b08SToby Isaac suffix: 0 153*345a4b08SToby Isaac 154*345a4b08SToby Isaac TEST*/ 155