# Searches for an installation of the PETSc library. On success, it sets the following variables:
#
#   PETSc_FOUND                Set to true to indicate the library was found
#   PETSc_INCLUDE_DIRS         The directory containing the main PETSc header file petsc.h
#   PETSc_LIBRARIES            All PETSc libraries (with full path)
#   PETSc_<component>_LIBRARY  Individual per-component libraries, where <component> is one of CONTRIB, DM, KSP, MAT, SNES,
#                              TS, VEC, BLAS, LAPACK, MPI
#
# To specify an additional directory to search, set PETSc_ROOT.
#
# TODO: Read library names and dependencies from installed config files instead, to better detect when BLAS, LAPACK, MPI etc.
# are actually necessary and when they are not, and also to detect inter-component dependencies.
#
# Author: Siddhartha Chaudhuri, 2008
#

# Look for the PETSc header, first in the user-specified location and then in the system locations
SET(PETSc_INCLUDE_DOC "The directory containing the PETSc header file petsc.h")
FIND_PATH(PETSc_INCLUDE_DIRS NAMES petsc.h PATHS ${PETSc_ROOT} ${PETSc_ROOT}/include DOC ${PETSc_INCLUDE_DOC} NO_DEFAULT_PATH)
IF(NOT PETSc_INCLUDE_DIRS)  # now look in system locations
  FIND_PATH(PETSc_INCLUDE_DIRS NAMES petsc.h DOC ${PETSc_INCLUDE_DOC})
ENDIF(NOT PETSc_INCLUDE_DIRS)

SET(PETSc_FOUND FALSE)

IF(PETSc_INCLUDE_DIRS)
  SET(PETSc_LIBRARY_DIRS ${PETSc_INCLUDE_DIRS})

  IF("${PETSc_LIBRARY_DIRS}" MATCHES "/include$")
    # Strip off the trailing "/include" in the path.
    GET_FILENAME_COMPONENT(PETSc_LIBRARY_DIRS ${PETSc_LIBRARY_DIRS} PATH)
  ENDIF("${PETSc_LIBRARY_DIRS}" MATCHES "/include$")

  IF(EXISTS "${PETSc_LIBRARY_DIRS}/lib")
    SET(PETSc_LIBRARY_DIRS ${PETSc_LIBRARY_DIRS}/lib)
  ENDIF(EXISTS "${PETSc_LIBRARY_DIRS}/lib")

  # petsc
  FIND_LIBRARY(PETSc_DEBUG_LIBRARY   NAMES petscd petsc_d libpetscd libpetsc_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_RELEASE_LIBRARY NAMES petsc libpetsc
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_LIBRARY)
  IF(PETSc_DEBUG_LIBRARY AND PETSc_RELEASE_LIBRARY)
    SET(PETSc_LIBRARY debug ${PETSc_DEBUG_LIBRARY} optimized ${PETSc_RELEASE_LIBRARY})
  ELSEIF(PETSc_DEBUG_LIBRARY)
    SET(PETSc_LIBRARY ${PETSc_DEBUG_LIBRARY})
  ELSEIF(PETSc_RELEASE_LIBRARY)
    SET(PETSc_LIBRARY ${PETSc_RELEASE_LIBRARY})
  ENDIF(PETSc_DEBUG_LIBRARY AND PETSc_RELEASE_LIBRARY)

  # petsccontrib
  FIND_LIBRARY(PETSc_CONTRIB_DEBUG_LIBRARY   NAMES petsccontribd petsccontrib_d libpetsccontribd libpetsccontrib_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_CONTRIB_RELEASE_LIBRARY NAMES petsccontrib libpetsccontrib
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_CONTRIB_LIBRARY)
  IF(PETSc_CONTRIB_DEBUG_LIBRARY AND PETSc_CONTRIB_RELEASE_LIBRARY)
    SET(PETSc_CONTRIB_LIBRARY debug ${PETSc_CONTRIB_DEBUG_LIBRARY} optimized ${PETSc_CONTRIB_RELEASE_LIBRARY})
  ELSEIF(PETSc_CONTRIB_DEBUG_LIBRARY)
    SET(PETSc_CONTRIB_LIBRARY ${PETSc_CONTRIB_DEBUG_LIBRARY})
  ELSEIF(PETSc_CONTRIB_RELEASE_LIBRARY)
    SET(PETSc_CONTRIB_LIBRARY ${PETSc_CONTRIB_RELEASE_LIBRARY})
  ENDIF(PETSc_CONTRIB_DEBUG_LIBRARY AND PETSc_CONTRIB_RELEASE_LIBRARY)

  # petscdm
  FIND_LIBRARY(PETSc_DM_DEBUG_LIBRARY   NAMES petscdmd petscdm_d libpetscdmd libpetscdm_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_DM_RELEASE_LIBRARY NAMES petscdm libpetscdm
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_DM_LIBRARY)
  IF(PETSc_DM_DEBUG_LIBRARY AND PETSc_DM_RELEASE_LIBRARY)
    SET(PETSc_DM_LIBRARY debug ${PETSc_DM_DEBUG_LIBRARY} optimized ${PETSc_DM_RELEASE_LIBRARY})
  ELSEIF(PETSc_DM_DEBUG_LIBRARY)
    SET(PETSc_DM_LIBRARY ${PETSc_DM_DEBUG_LIBRARY})
  ELSEIF(PETSc_DM_RELEASE_LIBRARY)
    SET(PETSc_DM_LIBRARY ${PETSc_DM_RELEASE_LIBRARY})
  ENDIF(PETSc_DM_DEBUG_LIBRARY AND PETSc_DM_RELEASE_LIBRARY)

  # petscksp
  FIND_LIBRARY(PETSc_KSP_DEBUG_LIBRARY   NAMES petsckspd petscksp_d libpetsckspd libpetscksp_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_KSP_RELEASE_LIBRARY NAMES petscksp libpetscksp
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_KSP_LIBRARY)
  IF(PETSc_KSP_DEBUG_LIBRARY AND PETSc_KSP_RELEASE_LIBRARY)
    SET(PETSc_KSP_LIBRARY debug ${PETSc_KSP_DEBUG_LIBRARY} optimized ${PETSc_KSP_RELEASE_LIBRARY})
  ELSEIF(PETSc_KSP_DEBUG_LIBRARY)
    SET(PETSc_KSP_LIBRARY ${PETSc_KSP_DEBUG_LIBRARY})
  ELSEIF(PETSc_KSP_RELEASE_LIBRARY)
    SET(PETSc_KSP_LIBRARY ${PETSc_KSP_RELEASE_LIBRARY})
  ENDIF(PETSc_KSP_DEBUG_LIBRARY AND PETSc_KSP_RELEASE_LIBRARY)

  # petscmat
  FIND_LIBRARY(PETSc_MAT_DEBUG_LIBRARY   NAMES petscmatd petscmat_d libpetscmatd libpetscmat_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_MAT_RELEASE_LIBRARY NAMES petscmat libpetscmat
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_MAT_LIBRARY)
  IF(PETSc_MAT_DEBUG_LIBRARY AND PETSc_MAT_RELEASE_LIBRARY)
    SET(PETSc_MAT_LIBRARY debug ${PETSc_MAT_DEBUG_LIBRARY} optimized ${PETSc_MAT_RELEASE_LIBRARY})
  ELSEIF(PETSc_MAT_DEBUG_LIBRARY)
    SET(PETSc_MAT_LIBRARY ${PETSc_MAT_DEBUG_LIBRARY})
  ELSEIF(PETSc_MAT_RELEASE_LIBRARY)
    SET(PETSc_MAT_LIBRARY ${PETSc_MAT_RELEASE_LIBRARY})
  ENDIF(PETSc_MAT_DEBUG_LIBRARY AND PETSc_MAT_RELEASE_LIBRARY)

  # petscsnes
  FIND_LIBRARY(PETSc_SNES_DEBUG_LIBRARY   NAMES petscsnesd petscsnes_d libpetscsnesd libpetscsnes_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_SNES_RELEASE_LIBRARY NAMES petscsnes libpetscsnes
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_SNES_LIBRARY)
  IF(PETSc_SNES_DEBUG_LIBRARY AND PETSc_SNES_RELEASE_LIBRARY)
    SET(PETSc_SNES_LIBRARY debug ${PETSc_SNES_DEBUG_LIBRARY} optimized ${PETSc_SNES_RELEASE_LIBRARY})
  ELSEIF(PETSc_SNES_DEBUG_LIBRARY)
    SET(PETSc_SNES_LIBRARY ${PETSc_SNES_DEBUG_LIBRARY})
  ELSEIF(PETSc_SNES_RELEASE_LIBRARY)
    SET(PETSc_SNES_LIBRARY ${PETSc_SNES_RELEASE_LIBRARY})
  ENDIF(PETSc_SNES_DEBUG_LIBRARY AND PETSc_SNES_RELEASE_LIBRARY)

  # petscts
  FIND_LIBRARY(PETSc_TS_DEBUG_LIBRARY   NAMES petsctsd petscts_d libpetsctsd libpetscts_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_TS_RELEASE_LIBRARY NAMES petscts libpetscts
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_TS_LIBRARY)
  IF(PETSc_TS_DEBUG_LIBRARY AND PETSc_TS_RELEASE_LIBRARY)
    SET(PETSc_TS_LIBRARY debug ${PETSc_TS_DEBUG_LIBRARY} optimized ${PETSc_TS_RELEASE_LIBRARY})
  ELSEIF(PETSc_TS_DEBUG_LIBRARY)
    SET(PETSc_TS_LIBRARY ${PETSc_TS_DEBUG_LIBRARY})
  ELSEIF(PETSc_TS_RELEASE_LIBRARY)
    SET(PETSc_TS_LIBRARY ${PETSc_TS_RELEASE_LIBRARY})
  ENDIF(PETSc_TS_DEBUG_LIBRARY AND PETSc_TS_RELEASE_LIBRARY)

  # petscvec
  FIND_LIBRARY(PETSc_VEC_DEBUG_LIBRARY   NAMES petscvecd petscvec_d libpetscvecd libpetscvec_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_VEC_RELEASE_LIBRARY NAMES petscvec libpetscvec
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_VEC_LIBRARY)
  IF(PETSc_VEC_DEBUG_LIBRARY AND PETSc_VEC_RELEASE_LIBRARY)
    SET(PETSc_VEC_LIBRARY debug ${PETSc_VEC_DEBUG_LIBRARY} optimized ${PETSc_VEC_RELEASE_LIBRARY})
  ELSEIF(PETSc_VEC_DEBUG_LIBRARY)
    SET(PETSc_VEC_LIBRARY ${PETSc_VEC_DEBUG_LIBRARY})
  ELSEIF(PETSc_VEC_RELEASE_LIBRARY)
    SET(PETSc_VEC_LIBRARY ${PETSc_VEC_RELEASE_LIBRARY})
  ENDIF(PETSc_VEC_DEBUG_LIBRARY AND PETSc_VEC_RELEASE_LIBRARY)

  # BLAS
  FIND_LIBRARY(PETSc_BLAS_DEBUG_LIBRARY   NAMES f2cblasd f2cblas_d libf2cblasd libf2cblas_d blasd blas_d libblasd libblas_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_BLAS_RELEASE_LIBRARY NAMES f2cblas libf2cblas blas libblas
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_BLAS_LIBRARY)
  IF(PETSc_BLAS_DEBUG_LIBRARY AND PETSc_BLAS_RELEASE_LIBRARY)
    SET(PETSc_BLAS_LIBRARY debug ${PETSc_BLAS_DEBUG_LIBRARY} optimized ${PETSc_BLAS_RELEASE_LIBRARY})
  ELSEIF(PETSc_BLAS_DEBUG_LIBRARY)
    SET(PETSc_BLAS_LIBRARY ${PETSc_BLAS_DEBUG_LIBRARY})
  ELSEIF(PETSc_BLAS_RELEASE_LIBRARY)
    SET(PETSc_BLAS_LIBRARY ${PETSc_BLAS_RELEASE_LIBRARY})
  ENDIF(PETSc_BLAS_DEBUG_LIBRARY AND PETSc_BLAS_RELEASE_LIBRARY)

  # LAPACK
  FIND_LIBRARY(PETSc_LAPACK_DEBUG_LIBRARY   NAMES f2clapackd f2clapack_d libf2clapackd libf2clapack_d
                                                  lapackd lapack_d liblapackd liblapack_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_LAPACK_RELEASE_LIBRARY NAMES f2clapack f2clapack lapack liblapack
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_LAPACK_LIBRARY)
  IF(PETSc_LAPACK_DEBUG_LIBRARY AND PETSc_LAPACK_RELEASE_LIBRARY)
    SET(PETSc_LAPACK_LIBRARY debug ${PETSc_LAPACK_DEBUG_LIBRARY} optimized ${PETSc_LAPACK_RELEASE_LIBRARY})
  ELSEIF(PETSc_LAPACK_DEBUG_LIBRARY)
    SET(PETSc_LAPACK_LIBRARY ${PETSc_LAPACK_DEBUG_LIBRARY})
  ELSEIF(PETSc_LAPACK_RELEASE_LIBRARY)
    SET(PETSc_LAPACK_LIBRARY ${PETSc_LAPACK_RELEASE_LIBRARY})
  ENDIF(PETSc_LAPACK_DEBUG_LIBRARY AND PETSc_LAPACK_RELEASE_LIBRARY)

  # MPI
  FIND_LIBRARY(PETSc_MPI_DEBUG_LIBRARY   NAMES mpichd mpich_d libmpichd libmpich_d
               PATH_SUFFIXES "" Debug   PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)
  FIND_LIBRARY(PETSc_MPI_RELEASE_LIBRARY NAMES mpich libmpich
               PATH_SUFFIXES "" Release PATHS ${PETSc_LIBRARY_DIRS} NO_DEFAULT_PATH)

  SET(PETSc_MPI_LIBRARY)
  IF(PETSc_MPI_DEBUG_LIBRARY AND PETSc_MPI_RELEASE_LIBRARY)
    SET(PETSc_MPI_LIBRARY debug ${PETSc_MPI_DEBUG_LIBRARY} optimized ${PETSc_MPI_RELEASE_LIBRARY})
  ELSEIF(PETSc_MPI_DEBUG_LIBRARY)
    SET(PETSc_MPI_LIBRARY ${PETSc_MPI_DEBUG_LIBRARY})
  ELSEIF(PETSc_MPI_RELEASE_LIBRARY)
    SET(PETSc_MPI_LIBRARY ${PETSc_MPI_RELEASE_LIBRARY})
  ENDIF(PETSc_MPI_DEBUG_LIBRARY AND PETSc_MPI_RELEASE_LIBRARY)

  SET(PETSc_LIBRARIES)
  IF(PETSc_LIBRARY)
    SET(PETSc_FOUND TRUE)
    # Order of components is important because there are inter-component dependencies (see conf/variables)
    SET(PETSc_LIBRARIES ${PETSc_CONTRIB_LIBRARY}
                        ${PETSc_TS_LIBRARY}
                        ${PETSc_SNES_LIBRARY}
                        ${PETSc_KSP_LIBRARY}
                        ${PETSc_DM_LIBRARY}
                        ${PETSc_MAT_LIBRARY}
                        ${PETSc_VEC_LIBRARY}
                        ${PETSc_LIBRARY}
                        ${PETSc_MPI_LIBRARY}
                        ${PETSc_LAPACK_LIBRARY}
                        ${PETSc_BLAS_LIBRARY})
  ENDIF(PETSc_LIBRARY)
ENDIF(PETSc_INCLUDE_DIRS)

IF(PETSc_FOUND)
  IF(NOT PETSc_FIND_QUIETLY)
    MESSAGE(STATUS "Found PETSc: headers at ${PETSc_INCLUDE_DIRS}, libraries at ${PETSc_LIBRARY_DIRS}")
  ENDIF(NOT PETSc_FIND_QUIETLY)
ELSE(PETSc_FOUND)
  IF(PETSc_FIND_REQUIRED)
    MESSAGE(FATAL_ERROR "PETSc not found")
  ENDIF(PETSc_FIND_REQUIRED)
ENDIF(PETSc_FOUND)
