/*@ MatSchurComplementComputeExplicitOperator - Compute the Schur complement matrix explicitly Collective on Mat Input Parameter: . M - the matrix obtained with MatCreateSchurComplement() Output Parameter: . S - the Schur complement matrix Note: This can be expensive, so it is mainly for testing Level: advanced .seealso: MatCreateSchurComplement(), MatSchurComplementUpdate() @*/ PetscErrorCode MatSchurComplementComputeExplicitOperator(Mat M, Mat *S) { Mat B, C, D; KSP ksp; PC pc; PetscBool isLU, isILU; PetscReal fill = 2.0; PetscErrorCode ierr; PetscFunctionBegin; ierr = MatSchurComplementGetSubMatrices(M, NULL, NULL, &B, &C, &D);CHKERRQ(ierr); ierr = MatSchurComplementGetKSP(M, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) pc, PCLU, &isLU);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) pc, PCILU, &isILU);CHKERRQ(ierr); if (isLU || isILU) { Mat fact, Bd, AinvB, AinvBd; PetscReal eps = 1.0e-10; /* This can be sped up for banded LU */ ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = PCFactorGetMatrix(pc, &fact);CHKERRQ(ierr); ierr = MatConvert(B, MATDENSE, MAT_INITIAL_MATRIX, &Bd);CHKERRQ(ierr); ierr = MatDuplicate(Bd, MAT_DO_NOT_COPY_VALUES, &AinvBd);CHKERRQ(ierr); ierr = MatMatSolve(fact, Bd, AinvBd);CHKERRQ(ierr); ierr = MatDestroy(&Bd);CHKERRQ(ierr); ierr = MatChop(AinvBd, eps);CHKERRQ(ierr); ierr = MatConvert(AinvBd, MATAIJ, MAT_INITIAL_MATRIX, &AinvB);CHKERRQ(ierr); ierr = MatDestroy(&AinvBd);CHKERRQ(ierr); ierr = MatMatMult(C, AinvB, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); ierr = MatDestroy(&AinvB);CHKERRQ(ierr); } else { Mat Ainvd, Ainv; ierr = PCComputeExplicitOperator(pc, &Ainvd);CHKERRQ(ierr); ierr = MatConvert(Ainvd, MATAIJ, MAT_INITIAL_MATRIX, &Ainv);CHKERRQ(ierr); ierr = MatDestroy(&Ainvd);CHKERRQ(ierr); #if 0 /* Symmetric version */ ierr = MatPtAP(Ainv, B, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); #else /* Nonsymmetric version */ ierr = MatMatMatMult(C, Ainv, B, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); #endif ierr = MatDestroy(&Ainv);CHKERRQ(ierr); } ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); ierr = MatView(*S, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); if (D) { MatInfo info; ierr = MatGetInfo(D, MAT_GLOBAL_SUM, &info);CHKERRQ(ierr); if (info.nz_used) SETERRQ(PetscObjectComm((PetscObject) M), PETSC_ERR_SUP, "Not yet implemented"); } PetscFunctionReturn(0); }
/*@ MatSchurComplementComputeExplicitOperator - Compute the Schur complement matrix explicitly Collective on Mat Input Parameter: . M - the matrix obtained with MatCreateSchurComplement() Output Parameter: . S - the Schur complement matrix Note: This can be expensive, so it is mainly for testing Level: advanced .seealso: MatCreateSchurComplement(), MatSchurComplementUpdate() @*/ PetscErrorCode MatSchurComplementComputeExplicitOperator(Mat M, Mat *S) { Mat B, C, D; KSP ksp; PC pc; PetscBool isLU, isILU; PetscReal fill = 2.0; PetscErrorCode ierr; PetscFunctionBegin; ierr = MatSchurComplementGetSubMatrices(M, NULL, NULL, &B, &C, &D);CHKERRQ(ierr); ierr = MatSchurComplementGetKSP(M, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) pc, PCLU, &isLU);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) pc, PCILU, &isILU);CHKERRQ(ierr); if (isLU || isILU) { Mat fact, Bd, AinvB, AinvBd; PetscReal eps = 1.0e-10; /* This can be sped up for banded LU */ ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = PCFactorGetMatrix(pc, &fact);CHKERRQ(ierr); ierr = MatConvert(B, MATDENSE, MAT_INITIAL_MATRIX, &Bd);CHKERRQ(ierr); ierr = MatDuplicate(Bd, MAT_DO_NOT_COPY_VALUES, &AinvBd);CHKERRQ(ierr); ierr = MatMatSolve(fact, Bd, AinvBd);CHKERRQ(ierr); ierr = MatDestroy(&Bd);CHKERRQ(ierr); ierr = MatChop(AinvBd, eps);CHKERRQ(ierr); ierr = MatConvert(AinvBd, MATAIJ, MAT_INITIAL_MATRIX, &AinvB);CHKERRQ(ierr); ierr = MatDestroy(&AinvBd);CHKERRQ(ierr); ierr = MatMatMult(C, AinvB, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); ierr = MatDestroy(&AinvB);CHKERRQ(ierr); } else { Mat Ainvd, Ainv; ierr = PCComputeExplicitOperator(pc, &Ainvd);CHKERRQ(ierr); ierr = MatConvert(Ainvd, MATAIJ, MAT_INITIAL_MATRIX, &Ainv);CHKERRQ(ierr); ierr = MatDestroy(&Ainvd);CHKERRQ(ierr); #if 0 /* Symmetric version */ ierr = MatPtAP(Ainv, B, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); #else /* Nonsymmetric version */ ierr = MatMatMatMult(C, Ainv, B, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); #endif ierr = MatDestroy(&Ainv);CHKERRQ(ierr); } if (D) { ierr = MatAXPY(*S, -1.0, D, DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); } ierr = MatScale(*S,-1.0);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc, char *argv[]) { // Initialize libMesh libMesh::LibMeshInit init(argc, argv); libMesh::Parallel::Communicator& WorldComm = init.comm(); libMesh::PetscMatrix<libMesh::Number> matrix_A(WorldComm); matrix_A.init(4,4,4,4); matrix_A.set(0,0,1.); // matrix_A.set(0,1,2.); // matrix_A.set(0,2,3.); // matrix_A.set(0,3,4.); // matrix_A.set(1,0,2.); matrix_A.set(1,1,5.); // matrix_A.set(1,2,3.); // matrix_A.set(1,3,7.); // matrix_A.set(2,0,3.); // matrix_A.set(2,1,3.); matrix_A.set(2,2,9.); // matrix_A.set(2,3,6.); // matrix_A.set(3,0,4.); // matrix_A.set(3,1,7.); // matrix_A.set(3,2,6.); matrix_A.set(3,3,1.); matrix_A.close(); Mat dummy_inv_A; MatCreate(PETSC_COMM_WORLD,&dummy_inv_A); MatSetType(dummy_inv_A,MATMPIAIJ); MatSetSizes(dummy_inv_A,PETSC_DECIDE,PETSC_DECIDE,4,4); MatMPIAIJSetPreallocation(dummy_inv_A,2,NULL,0,NULL); MatSetUp(dummy_inv_A); // Dummy matrices // Mat dummy_A, dummy_inv_A; // // libMesh::PetscVector<libMesh::Number> vector_unity(WorldComm,4,4); libMesh::PetscVector<libMesh::Number> vector_dummy_answer(WorldComm,4,4); VecSet(vector_unity.vec(),1); vector_unity.close(); VecSet(vector_dummy_answer.vec(),0); vector_dummy_answer.close(); // Solver // libMesh::PetscLinearSolver<libMesh::Number> KSP_dummy_solver(WorldComm); // KSP_dummy_solver.init(&matrix_A); // KSPSetOperators(KSP_dummy_solver.ksp(),matrix_A.mat(),NULL); KSP ksp; PC pc; KSPCreate(PETSC_COMM_WORLD,&ksp); KSPSetOperators(ksp, matrix_A.mat(), matrix_A.mat()); KSPGetPC(ksp,&pc); PCSetFromOptions(pc); PCType dummy_type; PCGetType(pc,&dummy_type); std::cout << std::endl << dummy_type << std::endl << std::endl; // PCSetType(pc,PCSPAI); // PCHYPRESetType(pc,"parasails"); KSPSetUp(ksp); KSPSolve(ksp,vector_unity.vec(),vector_dummy_answer.vec()); PCComputeExplicitOperator(pc,&dummy_inv_A); // KSPGetOperators(KSP_dummy_solver.ksp(),&dummy_A,&dummy_inv_A); libMesh::PetscMatrix<libMesh::Number> matrix_invA(dummy_inv_A,WorldComm); matrix_invA.close(); // // // KSP_dummy_solver.solve(matrix_A,vector_dummy_answer,vector_unity,1E-5,10000); // // vector_dummy_answer.print_matlab(); // // libMesh::PetscMatrix<libMesh::Number> product_mat(WorldComm); matrix_A.print_matlab(); matrix_invA.print_matlab(); vector_dummy_answer.print_matlab(); return 0; }
PETSC_EXTERN void PETSC_STDCALL pccomputeexplicitoperator_(PC pc,Mat *mat, int *__ierr ){ *__ierr = PCComputeExplicitOperator( (PC)PetscToPointer((pc) ),mat); }