# For the installer process we need a single directory
# where we put all module files
SET(CMAKE_Fortran_MODULE_DIRECTORY
  ${PROJECT_BINARY_DIR}/fmodules CACHE PATH "Directory for Fortran modules")

ADD_SUBDIRECTORY(binio)
ADD_SUBDIRECTORY(modules)
ADD_SUBDIRECTORY(view3d)
ADD_SUBDIRECTORY(viewaxis)

IF(WITH_MPI)
  SET(ELMERSOLVER_OUTPUT_NAME "ElmerSolver_mpi") 
ELSE()
  SET(ELMERSOLVER_OUTPUT_NAME "ElmerSolver")
ENDIF()

SET(prefix "${CMAKE_INSTALL_PREFIX}")

SET(solverlib_SOURCES AddrFunc.F90 NavierStokes.F90 NavierStokesGeneral.F90
  NavierStokesCylindrical.F90 Lists.F90
  DiffuseConvectiveAnisotropic.F90 LoadMod.F90
  DiffuseConvectiveGeneralAnisotropic.F90 PElementMaps.F90
  PElementBase.F90 ElementDescription.F90 Integration.F90 ListMatrixArray.F90
  ModelDescription.F90 GeneralUtils.F90 Stress.F90 StressGeneral.F90
  LinearAlgebra.F90 CoordinateSystems.F90 ListMatrix.F90 CRSMatrix.F90
  BandMatrix.F90 BandwidthOptimize.F90 BlockSolve.F90
  MaterialModels.F90 DirectSolve.F90 IterSolve.F90
  IterativeMethods.F90 TimeIntegrate.F90 Types.F90 SolveBand.F90
  ElementUtils.F90 Radiation.F90 fft.c Load.c Differentials.F90
  FreeSurface.F90 Maxwell.F90 MaxwellAxiS.F90 MaxwellGeneral.F90
  Walls.F90 SolverUtils.F90 SolveSBand.F90 CPUTime.c Interpolation.F90
  MainUtils.F90 Adaptive.F90 EigenSolve.F90 HashTable.F90
  MeshUtils.F90 SaveUtils.F90 SParIterGlobals.F90 SParIterComm.F90
  SParIterPrecond.F90 SParIterSolver.F90 Messages.F90 Multigrid.F90
  Smoothers.F90 ClusteringMethods.F90 ParallelUtils.F90
  ParallelEigenSolve.F90 solve_cmplx.F90 solve_real.F90 MGPrec.F90
  DefUtils.F90 MeshPartition.F90 MeshRemeshing.F90 LUDecomposition.F90 
  RadiationFactors.F90 f_stubs.c
  ExchangeCorrelations.F90 SolveHypre.c SolverActivate_x.F90
  SolveTrilinos.cxx SolveSuperLU.c iso_varying_string.F90
  umf4_f77wrapper.c VankaCreate.F90 ParticleUtils.F90 Feti.F90
  cholmod.c InterpolateMeshToMesh.F90 InterpVarToVar.F90
  LinearForms.F90 H1Basis.F90 CircuitUtils.F90 BackwardError.F90
  ElmerSolver.F90 MagnetoDynamicsUtils.F90 ComponentUtils.F90 
  ZirkaHysteresis.F90 SolidMechanicsUtils.F90)

SET_PROPERTY(SOURCE MaxwellAxiS.F90 PROPERTY
	COMPILE_DEFINITIONS FULL_INDUCTION)


IF(WITH_LUA)
  INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR})
  LIST(APPEND solverlib_SOURCES Lua.F90 elmer_lua_iface.c)
  INSTALL(DIRECTORY lua-scripts DESTINATION share/elmersolver/
    PATTERN lua-scripts/*.lua)
  FILE(GLOB DEFAULT_LUA_SCRIPTS "lua-scripts/*.lua")
  FILE(COPY ${DEFAULT_LUA_SCRIPTS} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/share/elmersolver/lua-scripts/)
ENDIF()

IF(HAVE_FETI4I)
  LIST(APPEND solverlib_SOURCES ${FETI4I_INTERFACE_SOURCE})
ENDIF()

#FILE(GLOB SRC_FILES *.src)
#FOREACH(FNAME ${SRC_FILES})
#GET_FILENAME_COMPONENT(BASENAME ${FNAME} NAME_WE)
#ADD_CUSTOM_COMMAND(
  #OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BASENAME}.F90
  #COMMAND ${CMAKE_COMMAND} -E copy ${FNAME}
    #${CMAKE_CURRENT_BINARY_DIR}/${BASENAME}.F90
  #DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${BASENAME}.src
  #)
#ENDFOREACH()

INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}/fem/src")
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/fhutiter/src")
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/binio")
INCLUDE_DIRECTORIES("${PROJECT_BINARY_DIR}/fhutiter/src")

IF(WITH_Trilinos)
  INCLUDE_DIRECTORIES("${Epetra_INCLUDE_DIRS}")
  INCLUDE_DIRECTORIES("${ML_INCLUDE_DIRS}")
ENDIF()

# Extract additional compile flags
GET_DIRECTORY_PROPERTY( ELMER_CDEFS COMPILE_DEFINITIONS )
FOREACH( d ${ELMER_CDEFS} )
	 SET(ELMER_F90FLAGS "${ELMER_F90FLAGS} -D${d}")
ENDFOREACH()


# Extract compile flags arising from build type
IF(CMAKE_BUILD_TYPE)
  STRING(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPCASE)
  SET(ELMER_F90FLAGS "${ELMER_F90FLAGS} ${CMAKE_Fortran_FLAGS_${CMAKE_BUILD_TYPE_UPCASE}}")
  MARK_AS_ADVANCED(CMAKE_BUILD_TYPE_UPCASE)
ENDIF(CMAKE_BUILD_TYPE)

# Output elmerf90 and elmerld
SET(HAVE_ELMERICE "FALSE")
IF(WITH_ElmerIce)
  SET(HAVE_ELMERICE "TRUE")
ENDIF()

IF(WIN32)
  CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/elmerf90.bat.in.cmake
	  ${CMAKE_CURRENT_BINARY_DIR}/elmerf90.bat)
  CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/elmerld.bat.in.cmake
	  ${CMAKE_CURRENT_BINARY_DIR}/elmerld.bat)
ENDIF()

CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/elmerf90-nosh.in.cmake
  ${CMAKE_CURRENT_BINARY_DIR}/elmerf90-nosh)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/elmerf90.in.cmake
  ${CMAKE_CURRENT_BINARY_DIR}/elmerf90)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/elmerld.in.cmake
  ${CMAKE_CURRENT_BINARY_DIR}/elmerld)

# Create pkg-config file if requested and place it under ${PKGCONFIG_PC_PATH}
# Defaults: PKGCONFIG_PC_PATH = ${CMAKE_INSTALL_PREFIX}/share/pkgconfig
IF(CREATE_PKGCONFIG_FILE)
  SET(PKGCONFIG_PC_PATH "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" 
    CACHE PATH "Path where to install elmer pkg-config file")
  CONFIGURE_FILE(elmer.pc.cmake elmer.pc @ONLY)
  INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/elmer.pc 
    DESTINATION ${PKGCONFIG_PC_PATH})
ENDIF(CREATE_PKGCONFIG_FILE)

# Copy elements.def and SOLVER.KEYWORDS (to enable testing)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/elements.def 
  ${CMAKE_CURRENT_BINARY_DIR}/elements.def COPYONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/SOLVER.KEYWORDS
  ${CMAKE_CURRENT_BINARY_DIR}/SOLVER.KEYWORDS COPYONLY)

IF (NOT MPI_FOUND)
  FILE(COPY ${CMAKE_CURRENT_SOURCE_DIR}/mpif_stub.h 
            DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
  FILE(RENAME ${CMAKE_CURRENT_BINARY_DIR}/mpif_stub.h
              ${CMAKE_CURRENT_BINARY_DIR}/mpif.h)
ENDIF()

ADD_LIBRARY(mpi_stubs SHARED mpif_stubs.F90)
ADD_LIBRARY(elmersolver SHARED ${solverlib_SOURCES})
SET_TARGET_PROPERTIES(mpi_stubs
                      PROPERTIES LINKER_LANGUAGE Fortran)
SET_TARGET_PROPERTIES(elmersolver
                      PROPERTIES LINKER_LANGUAGE Fortran)

#We want MMG & Zoltan in the RPATH (if found), but given how many other 
#components use ELMERSOLVER_RPATH_STRING, it seemed best to make
#a local copy just for ElmerSolver and libelmersolver
SET(ELMERSOLVER_RPATH_STRING_MOD "${ELMERSOLVER_RPATH_STRING}")
IF(HAVE_MMG)
  TARGET_LINK_LIBRARIES(elmersolver ${MMG_LIBRARY})
  SET(ELMERSOLVER_RPATH_STRING_MOD "${ELMERSOLVER_RPATH_STRING_MOD}:${MMG_LIBDIR}")
  SET(ELMERLIB_RPATH_STRING "${ELMERLIB_RPATH_STRING}:${MMG_LIBDIR}")
  #TODO - add to RPath
ENDIF()

IF(HAVE_ZOLTAN)
  TARGET_LINK_LIBRARIES(elmersolver ${ZOLTAN_LIBRARY})
  ADD_DEPENDENCIES(elmersolver ${ZOLTAN_LIBRARY})
  # SET(ELMERSOLVER_RPATH_STRING_MOD "${ELMERSOLVER_RPATH_STRING_MOD}/:${ZOLTAN_LIBDIR}")
  # SET(ELMERLIB_RPATH_STRING "${ELMERLIB_RPATH_STRING}/:${ZOLTAN_LIBDIR}")
ENDIF()

# ElmerSolver libraries 
SET(ELMERSOLVER_LIBRARIES matc umfpack 
                          amd fhuti binio arpack
                          ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} 
                          ${CMAKE_DL_LIBS})

IF(WITH_LUA)
  LIST(APPEND ELMERSOLVER_LIBRARIES ${LUA_LIBRARIES})
ENDIF()


ADD_EXECUTABLE(Solver_TGT Solver.F90)
SET_TARGET_PROPERTIES(Solver_TGT PROPERTIES OUTPUT_NAME "${ELMERSOLVER_OUTPUT_NAME}")

IF(NOT(WIN32))
  MESSAGE(STATUS " ELMERSOLVER_RPATH_STRING_MOD " ${ELMERSOLVER_RPATH_STRING_MOD})
  MESSAGE(STATUS " ELMERLIB_RPATH_STRING " ${ELMERLIB_RPATH_STRING})

   SET_TARGET_PROPERTIES(Solver_TGT PROPERTIES INSTALL_RPATH "${ELMERSOLVER_RPATH_STRING_MOD}")
   SET_TARGET_PROPERTIES(elmersolver PROPERTIES INSTALL_RPATH "${ELMERLIB_RPATH_STRING}")
ENDIF()

IF(NOT(WITH_MPI))
  TARGET_LINK_LIBRARIES(elmersolver mpi_stubs ${ELMERSOLVER_LIBRARIES})
  TARGET_LINK_LIBRARIES(Solver_TGT elmersolver)
ENDIF()

# ElmerSolver libraries 
IF(WITH_MPI)
  #ADD_LIBRARY(elmersolver_mpi SHARED ${solverlib_SOURCES})

  # Add parpack and possibly others
  IF(Mumps_LIBRARIES)
    INCLUDE_DIRECTORIES(${Mumps_INCLUDE_DIR})
    # Link to SCALAPACK implicitly
    LIST(APPEND ELMERSOLVER_LIBRARIES ${Mumps_LIBRARIES})
  ELSEIF(MKL_CPARDISO_FOUND)
    # Mumps includes SCALAPACK, but it is needed with CPARDISO
    LIST(APPEND ELMERSOLVER_LIBRARIES ${SCALAPACK_LIBRARIES})
  ENDIF()

  IF(Hypre_LIBRARIES)
    LIST(APPEND ELMERSOLVER_LIBRARIES ${Hypre_LIBRARIES})
  ENDIF()

  IF(FETI4I_LIBRARIES)
    LIST(APPEND ELMERSOLVER_LIBRARIES ${FETI4I_LIBRARIES})
  ENDIF()
   
  # Executable
  GET_TARGET_PROPERTY(CURRENT_LINK_FLAGS Solver_TGT LINK_FLAGS)
  GET_TARGET_PROPERTY(CURRENT_COMPILE_FLAGS Solver_TGT COMPILE_FLAGS)

  IF(CURRENT_LINK_FLAGS)
    SET(CURR_LFLAGS "${CURRENT_LINK_FLAGS};${MPI_Fortran_LINK_FLAGS}")
  ELSE()
    SET(CURR_LFLAGS "${MPI_Fortran_LINK_FLAGS}")
  ENDIF()

  IF(CURRENT_COMPILE_FLAGS)
    SET(CURR_CFLAGS "${CURRENT_COMPILE_FLAGS};${MPI_Fortran_COMPILE_FLAGS}")
  ELSE()
    SET(CURR_CFLAGS "${MPI_Fortran_COMPILE_FLAGS}")
  ENDIF()

  SET_TARGET_PROPERTIES(Solver_TGT PROPERTIES LINK_FLAGS "${CURR_LFLAGS}")
  SET_TARGET_PROPERTIES(Solver_TGT PROPERTIES COMPILE_FLAGS "${CURR_CFLAGS}")
  TARGET_LINK_LIBRARIES(Solver_TGT elmersolver ${ELMERSOLVER_LIBRARIES})

  # Library object
  GET_TARGET_PROPERTY(CURRENT_LINK_FLAGS elmersolver LINK_FLAGS) 
  GET_TARGET_PROPERTY(CURRENT_COMPILE_FLAGS elmersolver COMPILE_FLAGS)

  IF(CURRENT_LINK_FLAGS)
    SET(CURR_LFLAGS "${CURRENT_LINK_FLAGS};${MPI_Fortran_LINK_FLAGS}")
  ELSE()
    SET(CURR_LFLAGS "${MPI_Fortran_LINK_FLAGS}")
  ENDIF()
  IF(CURRENT_COMPILE_FLAGS)
    SET(CURR_CFLAGS "${CURRENT_COMPILE_FLAGS};${MPI_Fortran_COMPILE_FLAGS}")
  ELSE()
    SET(CURR_CFLAGS "${MPI_Fortran_COMPILE_FLAGS}")
  ENDIF()

  SET_TARGET_PROPERTIES(elmersolver PROPERTIES LINK_FLAGS "${CURR_LFLAGS}")
  SET_TARGET_PROPERTIES(elmersolver PROPERTIES COMPILE_FLAGS "${CURR_CFLAGS}")
  TARGET_LINK_LIBRARIES(elmersolver ${ELMERSOLVER_LIBRARIES} parpack ${MPI_Fortran_LIBRARIES})

  SET(SERIAL_SOLVER_FILEPATH "${CMAKE_INSTALL_PREFIX}/bin/ElmerSolver")
  SET(MPI_SOLVER_FILEPATH "${CMAKE_INSTALL_PREFIX}/bin/${ELMERSOLVER_OUTPUT_NAME}")
ENDIF()

IF(WITH_Trilinos)
  TARGET_LINK_LIBRARIES(elmersolver "${Trilinos_LIBRARIES};${ML_LIBRARIES};${Epetra_LIBRARIES};${Teuchos_LIBRARIES}")
ENDIF()

# elmersolver -library
#TARGET_LINK_LIBRARIES(elmersolver ${ELMERSOLVER_LIBRARIES})

## ElmerSolver serial
#IF(NOT(NO_SERIAL_BINARY))
  #TARGET_LINK_LIBRARIES(elmersolver mpi_stubs ${ELMERSOLVER_LIBRARIES})
  #TARGET_LINK_LIBRARIES(ElmerSolver elmersolver)
#ENDIF()

# ElmerSolver
#ADD_EXECUTABLE(ElmerSolver Solver.F90)
#TARGET_LINK_LIBRARIES(ElmerSolver ${ELMERSOLVER_LIBRARIES} 
                                  #mpi_stubs)

# ViewFactors
ADD_EXECUTABLE(ViewFactors ViewFactors.F90)
SET_TARGET_PROPERTIES(ViewFactors PROPERTIES LINKER_LANGUAGE Fortran)
# TARGET_INCLUDE_DIRECTORIES(ViewFactors PUBLIC ${CMAKE_BINARY_DIR}/fem/src/view3d)
# TARGET_INCLUDE_DIRECTORIES(ViewFactors PUBLIC ${CMAKE_BINARY_DIR}/fem/src/viewfactors)
# FIND_LIBRARY(VIEW3D_LIBRARIES PATHS ${CMAKE_CURRENT_BINARY_DIR}/view3d)
# FIND_LIBRARY(VIEWAXIS_LIBRARIES PATHS ${CMAKE_CURRENT_BINARY_DIR}/viewaxis)
TARGET_LINK_LIBRARIES(ViewFactors ${ELMERSOLVER_LIBRARIES} 
                                  mpi_stubs
				  view3d
				  viewaxis elmersolver)
INSTALL(TARGETS ViewFactors RUNTIME DESTINATION "bin")

IF(NOT(WIN32))
  SET_TARGET_PROPERTIES(ViewFactors PROPERTIES INSTALL_RPATH "${ELMERSOLVER_RPATH_STRING}")
ENDIF()

# GebhardFactors
ADD_EXECUTABLE(GebhardtFactors GebhardtFactors.F90)
TARGET_LINK_LIBRARIES(GebhardtFactors ${ELMERSOLVER_LIBRARIES} 
                                      mpi_stubs elmersolver)

IF(NOT(WIN32))
  SET_TARGET_PROPERTIES(GebhardtFactors PROPERTIES INSTALL_RPATH "${ELMERSOLVER_RPATH_STRING}")
ENDIF()

IF(WITH_Trilinos)
  TARGET_LINK_LIBRARIES(GebhardtFactors elmersolver "${Trilinos_LIBRARIES};${Belos_LIBRARIES};${ML_LIBRARIES};${Epetra_LIBRARIES};${Teuchos_LIBRARIES}")
ENDIF()

INSTALL(TARGETS GebhardtFactors mpi_stubs RUNTIME DESTINATION "bin"
  LIBRARY DESTINATION "${ELMER_INSTALL_LIB_DIR}")

# Installation rules
INSTALL(FILES elements.def SOLVER.KEYWORDS DESTINATION "share/elmersolver/lib")


IF(NOT(WIN32))
  IF(WITH_MPI)
    INSTALL(TARGETS Solver_TGT elmersolver RUNTIME DESTINATION "bin"
      LIBRARY DESTINATION "${ELMER_INSTALL_LIB_DIR}")
    INSTALL(TARGETS Solver_TGT RUNTIME DESTINATION "bin"
      LIBRARY DESTINATION "${ELMER_INSTALL_LIB_DIR}")
  ELSE()
    INSTALL(TARGETS Solver_TGT elmersolver mpi_stubs RUNTIME DESTINATION "bin" 
      LIBRARY DESTINATION "${ELMER_INSTALL_LIB_DIR}")
  ENDIF()
ELSE()
  INSTALL(TARGETS elmersolver mpi_stubs RUNTIME DESTINATION "${ELMER_INSTALL_LIB_DIR}" 
    LIBRARY DESTINATION "${ELMER_INSTALL_LIB_DIR}")
  INSTALL(TARGETS Solver_TGT elmersolver mpi_stubs RUNTIME DESTINATION "bin" 
    LIBRARY DESTINATION "${ELMER_INSTALL_LIB_DIR}")
ENDIF()

IF(WIN32)
  INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/elmerf90.bat DESTINATION "bin")
  INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/elmerld.bat DESTINATION  "bin")
ENDIF()
INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/elmerf90 DESTINATION "bin")
INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/elmerld DESTINATION  "bin")

                  
INSTALL(DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY}/.
                  DESTINATION "share/elmersolver/include")

IF(WITH_MPI)
  IF(NOT(WIN32))
    # INSTALL(CODE "
    # EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E create_symlink ElmerSolver_mpi ElmerSolver
    # WORKING_DIRECTORY \${CMAKE_INSTALL_PREFIX}/bin)")
    ADD_CUSTOM_TARGET(elmersolver_link ALL COMMAND ${CMAKE_COMMAND} -E create_symlink ElmerSolver_mpi ElmerSolver)
    ADD_DEPENDENCIES(elmersolver_link Solver_TGT)
    INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/ElmerSolver DESTINATION "bin")
  ELSE()
    INSTALL(CODE "EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E copy
    \${CMAKE_INSTALL_PREFIX}/bin/ElmerSolver_mpi.exe
    \${CMAKE_INSTALL_PREFIX}/bin/ElmerSolver.exe)")
  ENDIF()
ENDIF()
