#include #include #include "macros.h" !==================================================================================================== PROGRAM test_nep !==================================================================================================== ! USE slepcnep IMPLICIT NONE NEP :: nep Mat :: A, B PetscMPIInt :: rank, nsize PetscViewer :: viewer PetscInt :: its PetscInt :: n = 10 PetscInt :: nev = 5 PetscInt :: maxit = 100 PetscReal :: tol = 1.0E-07 PetscScalar :: lambda PetscErrorCode :: ierr INTEGER :: ShellMat_Ax_iter INTEGER :: ShellMat_Bx_iter ! !.... initialize counters ShellMat_Ax_iter = 0 ShellMat_Bx_iter = 0 its = 0 ! !.... Initialize SLEPc PetscCall(SlepcInitialize(PETSC_NULL_CHARACTER, ierr)) ! !.... Option string PetscCall(PetscOptionsInsertString(PETSC_NULL_OPTIONS, "-pc_type none -rg_type interval -rg_interval_endpoints 0,10,0,0" , ierr)) ! !.... Print out message PetscCall(PetscPrintf(PETSC_COMM_SELF, "==============================\n", ierr)) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Nonlinear Eigenvalue Problem \n", ierr)) PetscCall(PetscPrintf(PETSC_COMM_SELF, "==============================\n", ierr)) ! !.... get size and rank of MPI process PetscCall(MPI_Comm_size(PETSC_COMM_SELF,nsize,ierr)) PetscCall(MPI_Comm_rank(PETSC_COMM_SELF,rank ,ierr)) ! !.... View command line table PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF,'stdout', viewer, ierr)) PetscCall(PetscOptionsView(PETSC_NULL_OPTIONS, viewer, ierr)) !.... Create matrix-free operators for A and B PetscCall(MatCreateShell(PETSC_COMM_SELF,n,n,PETSC_DETERMINE,PETSC_DETERMINE, PETSC_NULL_INTEGER, A, ierr)) PetscCall(MatCreateShell(PETSC_COMM_SELF,n,n,PETSC_DETERMINE,PETSC_DETERMINE, PETSC_NULL_INTEGER, B, ierr)) PetscCall(MatShellSetOperation(A, MATOP_MULT, MatMult_A, ierr)) PetscCall(MatShellSetOperation(B, MATOP_MULT, MatMult_B, ierr)) ! !.... Create nonlinear eigensolver PetscCall(NEPCreate(PETSC_COMM_SELF, nep, ierr)) ! !.... Set functions and Jacobians for NEP PetscCall(NEPSetFunction(nep, A, A, MyNEPFunction, PETSC_NULL_INTEGER, ierr)) PetscCall(NEPSetJacobian(nep, B, MyNEPJacobian, PETSC_NULL_INTEGER, ierr)) ! !.... Set the problem type PetscCall(NEPSetProblemType(nep, NEP_GENERAL, ierr)) ! !.... set the solver type PetscCall(NEPSetType(nep, NEPNLEIGS, ierr)) ! !.... Number of requested eigenvalues PetscCall(NEPSetDimensions(nep, nev, PETSC_DEFAULT_INTEGER, PETSC_DEFAULT_INTEGER, ierr)) ! !.... set stopping criteria PetscCall(NEPSetTolerances(nep, tol, maxit, ierr)) ! !.... Set solver parameters at runtime using command line options PetscCall(NEPSetFromOptions(nep, ierr)) ! !.... View NEP setup PetscCall(NEPView(nep, viewer, ierr)) ! !.... Print out message PetscCall(PetscPrintf(PETSC_COMM_SELF, "==============================\n", ierr)) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Nonlinear Eigenvalue Problem \n", ierr)) PetscCall(PetscPrintf(PETSC_COMM_SELF, "==============================\n", ierr)) ! !.... Solve the eigenvalue problem PetscCall(NEPSolve(nep, ierr)) ! !.... View NEP setup PetscCall(NEPView(nep, viewer, ierr)) ! !.... Get the number of converged eigenpairs PetscCall(NEPGetConverged(nep, nev, ierr)) ! !.... Destroy the eigensolver PetscCall(NEPDestroy(nep, ierr)) ! !.... Destroy matrices PetscCall(MatDestroy(A, ierr)) PetscCall(MatDestroy(B, ierr)) ! !.... Destroy the viewer (this has already been destroyed after PetscOptionsView, but if it was created again, then it would be destroyed here) PetscCall(PetscViewerDestroy(viewer, ierr)) ! !.... Finalize SLEPc PetscCall(SlepcFinalize(ierr)) CONTAINS ! !==================================================================================================== SUBROUTINE MyNEPFunction(nep, slepc_lambda, T, P, ctx, ierr) !==================================================================================================== ! NEP :: nep PetscScalar :: slepc_lambda Mat :: T, P PetscInt :: ctx PetscErrorCode :: ierr WRITE(*,FMT='(a)',ADVANCE='NO') 'F' lambda = slepc_lambda END SUBROUTINE MyNEPFunction ! !==================================================================================================== SUBROUTINE MyNEPJacobian(nep, slepc_lambda, T, P, ctx, ierr) !==================================================================================================== NEP :: nep PetscScalar :: slepc_lambda Mat :: T, P PetscInt :: ctx PetscErrorCode :: ierr WRITE(*,FMT='(a)',ADVANCE='NO') 'J' lambda = slepc_lambda END SUBROUTINE MyNEPJacobian ! !==================================================================================================== SUBROUTINE MatMult_A(A, x, y, ierr) !==================================================================================================== ! !.... declare passed variables Mat :: A Vec :: x, y PetscErrorCode :: ierr PetscScalar :: xArray(10) PetscInt :: indices(10) PetscScalar :: yArray(10) PetscScalar :: A_matrix(10,10) ! !.... Sample 10x10 matrix DATA A_matrix / & 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, & 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, & 0, 1, 4, 1, 0, 0, 0, 0, 0, 0, & 0, 0, 1, 5, 1, 0, 0, 0, 0, 0, & 0, 0, 0, 1, 6, 1, 0, 0, 0, 0, & 0, 0, 0, 0, 1, 7, 1, 0, 0, 0, & 0, 0, 0, 0, 0, 1, 8, 1, 0, 0, & 0, 0, 0, 0, 0, 0, 1, 9, 1, 0, & 0, 0, 0, 0, 0, 0, 0, 1, 10, 1, & 1, 0, 0, 0, 0, 0, 0, 0, 1, 2 / DATA indices /0,1,2,3,4,5,6,7,8,9/ ! !.... heartbeat and counter WRITE(*,FMT='(a)',ADVANCE='NO') 'A' ShellMat_Ax_iter = ShellMat_Ax_iter + 1 ! !.... Get local size of vector x CALL VecGetLocalSize(x, n, ierr) ! !.... If x is not of size 10, return an error IF (n .NE. 10) STOP "Error: x is not of size 10" ! !.... Get array of values from vector x using read-only access PetscCall(VecGetValues(x, n, indices, xArray, ierr)) ! !.... Compute multiplication for each row of A and set y values yArray = matmul(A_matrix,xArray) - lambda*xArray ! !.... Assemble the resulting vector y PetscCall(VecSetValues(y, n, indices, yArray, INSERT_VALUES, ierr)) PetscCall(VecAssemblyBegin(y, ierr)) PetscCall(VecAssemblyEnd (y, ierr)) END SUBROUTINE MatMult_A ! !==================================================================================================== SUBROUTINE MatMult_B(B, x, y, ierr) !==================================================================================================== ! Mat :: B Vec :: x Vec :: y PetscErrorCode :: ierr WRITE(*,FMT='(a)',ADVANCE='NO') 'B' ShellMat_Bx_iter = ShellMat_Bx_iter + 1 PetscCall(VecCopy(x,y,ierr)) PetscCall(VecScale(y, -1.0, ierr)) END SUBROUTINE MatMult_B END PROGRAM test_nep