module petsc_stuff use f90_kind ! Include PETSc files #include "finclude/petscvecdef.h" #include "finclude/petscmatdef.h" #include "finclude/petsckspdef.h" use petscvec use petscmat use petscksp implicit none contains subroutine init_petsc use f90_kind implicit none PetscErrorCode :: ierr call PetscInitialize(PETSC_NULL_CHARACTER,ierr) end subroutine init_petsc subroutine stop_petsc use f90_kind implicit none PetscErrorCode :: ierr call PetscFinalize(ierr) end subroutine stop_petsc subroutine init_petsc_vector(petsc_vector,no_rows) use f90_kind implicit none Vec :: petsc_vector integer, intent(in) :: no_rows PetscErrorCode :: ierr call VecCreate(PETSC_COMM_WORLD,petsc_vector,ierr) call VecSetSizes(petsc_vector,PETSC_DECIDE,no_rows,ierr) call VecSetFromOptions(petsc_vector,ierr) call VecZeroEntries(petsc_vector,ierr) end subroutine init_petsc_vector subroutine finalize_petsc_vector(petsc_vector) ! Turns the vector into its final form, i.e. no coefficients can be ! added after calling this subroutine. use f90_kind implicit none Vec :: petsc_vector PetscErrorCode :: ierr call VecAssemblyBegin(petsc_vector,ierr) call VecAssemblyEnd(petsc_vector,ierr) end subroutine finalize_petsc_vector subroutine init_petsc_matrix(petsc_matrix,no_rows,no_cols,no_entries_row) use f90_kind implicit none Mat :: petsc_matrix integer, intent(in) :: no_rows integer, intent(in) :: no_cols integer, intent(in) :: no_entries_row integer, dimension(:), allocatable :: entries_per_rows PetscErrorCode :: ierr allocate(entries_per_rows(1:no_rows)) entries_per_rows = no_entries_row call MatCreateSeqAIJ(PETSC_COMM_SELF,no_rows,no_cols, /*no_entries_row*/ 0,entries_per_rows,petsc_matrix,ierr) call MatZeroEntries(petsc_matrix,ierr) deallocate(entries_per_rows) end subroutine init_petsc_matrix subroutine finalize_petsc_matrix(petsc_matrix) ! Turns the matrix into its final form, i.e. no coefficients can be ! added after calling this subroutine. use f90_kind implicit none Mat :: petsc_matrix PetscErrorCode :: ierr call MatAssemblyBegin(petsc_matrix,MAT_FINAL_ASSEMBLY,ierr) call MatAssemblyEnd(petsc_matrix,MAT_FINAL_ASSEMBLY,ierr) end subroutine finalize_petsc_matrix subroutine finalize_petsc_solver(A_petsc,ksp_A) ! Turns the matrix into its final form, i.e. no coefficients can be ! added after calling this subroutine. use f90_kind implicit none Mat :: A_petsc KSP :: ksp_A PetscErrorCode :: ierr PC :: pcc call KSPCreate(PETSC_COMM_WORLD,ksp_A,ierr) call KSPSetOperators(ksp_A,A_petsc,A_petsc,DIFFERENT_NONZERO_PATTERN,ierr) call KSPSetType(ksp_A,KSPCG,ierr) call KSPGetPC(ksp_A,pcc,ierr) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! AMG preconditioner !call PCSetType(pcc,PCGAMG,ierr) ! ICC preconditioner call PCSetType(pcc,PCICC,ierr) call PCFactorSetShiftType(pcc,MAT_SHIFT_POSITIVE_DEFINITE,ierr) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! call PCSetFromOptions(pcc,ierr) call KSPSetFromOptions(ksp_A,ierr) call KSPSetUp(ksp_A,ierr) end subroutine finalize_petsc_solver subroutine addcoef_petsc_vector(petsc_vector,row,coef) use f90_kind implicit none Vec :: petsc_vector integer, intent(in) :: row real(dp), intent(in) :: coef PetscErrorCode :: ierr call VecSetValue(petsc_vector,row-1,coef,ADD_VALUES,ierr) end subroutine addcoef_petsc_vector subroutine addcoef_petsc_matrix(petsc_matrix,row,col,coef) use f90_kind implicit none Mat :: petsc_matrix integer, intent(in) :: row, col real(dp), intent(in) :: coef PetscInt :: m,n PetscErrorCode :: ierr call MatSetValue(petsc_matrix,row-1,col-1,coef,ADD_VALUES,ierr) end subroutine addcoef_petsc_matrix subroutine triple_mat_prod(A,B,C,s) ! calc C = s * A * B * A^T use f90_kind implicit none Mat :: A Mat :: B Mat :: C real(dp), intent(in) :: s Mat :: D PetscErrorCode :: ierr PetscInt :: m,n ! D = B * A^T call MatMatTransposeMult(B,A,MAT_INITIAL_MATRIX,PETSC_DEFAULT_DOUBLE_PRECISION,D,ierr) ! C = A * D call MatMatMult(A,D,Mat_initial_matrix,PETSC_DEFAULT_DOUBLE_PRECISION,C,ierr) ! C = s * C call MatScale(C,s,ierr) end subroutine triple_mat_prod subroutine solve_petsc_system(ksp_A,rhs_petsc,x_petsc,toler,maxiter,iter_done) ! Solves the system of equations with a given right hand side ! Initial guess can be provided in x ! ! TODO: Implement the use of the initial guess use f90_kind implicit none Vec :: rhs_petsc Vec :: x_petsc KSP :: ksp_A real(dp), intent(in) :: toler integer, intent(in) :: maxiter integer, intent(out) :: iter_done real(dp) :: resnorm real(dp) :: rtol real(dp) :: dtol PetscErrorCode :: ierr KSPConvergedReason :: reason rtol = toler dtol = 1.d100 call KSPSetTolerances(ksp_A,rtol,PETSC_DEFAULT_DOUBLE_PRECISION,dtol,maxiter,ierr) call KSPSolve(ksp_A,rhs_petsc,x_petsc,ierr) call KSPGetIterationNumber(ksp_A,iter_done,ierr) call KSPGetConvergedReason(ksp_A,reason,ierr) if (reason < 1) then WRITE (*,*) 'PANIC: solve_petsc_system: No convergence. reason ',reason iter_done = -1 * iter_done endif call KSPGetResidualNorm(ksp_A,resnorm,ierr) end subroutine solve_petsc_system end module petsc_stuff