# in subdirectory "build", run
# cmake ../src 
#
# for debuging (of the code:)
# cmake ../src -DCMAKE_BUILD_TYPE=Debug 
#
# for (speed) optimized executables
# cmake ../src -DCMAKE_BUILD_TYPE=Release -DUSE_MARCHNATIVE=ON
#
# 
#
# for verbosity regarding commands executed, use
# cmake ../src -DCMAKE_VERBOSE_MAKEFILE=ON
#
# to enable UMFPACK from specific directory (e.g. if not installed
# system wide )
# cmake ../src -DSUITESPARSE=${HOME}/local/downloads/src/SuiteSparse/ 
#
# 


string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" bin_is_src)
if( ${bin_is_src} )
  message(FATAL_ERROR 
  "Attempting in source build. \n"
  "This is strongly discouraged, because it mixes the build output "
  "and temporary data with the source code. \n"
  "Go to the build directory, and start the build there:\n"
  "  cd [feins_root]/build \n"
  "  cmake ../src \n"
  "  make \n")
endif( ${bin_is_src} )

# Project name is not mandatory, but you should use it
project(feins C Fortran)

# States that CMake required version must be >= 2.6
cmake_minimum_required(VERSION 2.6)

# Appends the cmake/modules path inside the MAKE_MODULE_PATH variable which stores the
# directories of additional CMake modules (eg MacroOutOfSourceBuild.cmake):
set(CMAKE_MODULE_PATH ${CMAKE_HOME_DIRECTORY}/../CMakeUMFPACKModules ${CMAKE_MODULE_PATH})


#
# define options
#
# remember to display them at the end and to write them to cache

option (USE_OPENMP 
        "use OpenMP (if the compiler supports it)" ON) 
option (USE_MARCHNATIVE 
        "use the \"-march=native\" automatic tuning of the gnu compiler" ON) 

# set default cmake build type to Debug or Release 
# (None Debug Release RelWithDebInfo MinSizeRel)
IF( NOT CMAKE_BUILD_TYPE )
   SET( CMAKE_BUILD_TYPE "Debug" )
#   SET( CMAKE_BUILD_TYPE "Release" )
ENDIF()



#
# Find mandatory BLAS and LAPACK
#
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)
SET (LIBS ${LIBS} ${LAPACK_LIBRARIES})

#
# Find optional SuiteSparse
#
IF ( NOT SUITESPARSE STREQUAL OFF)
  FIND_PACKAGE(UFCONFIG)
  FIND_PACKAGE(AMD)
  FIND_PACKAGE(UMFPACK)
ENDIF ( NOT SUITESPARSE STREQUAL OFF)

IF (UMFPACK_FOUND)
	# UFCONFIG and AMD are dependencies
	MESSAGE (STATUS " -> UMFPACK support enabled ")
	SET (INCLUDE_DIR ${INCLUDE_DIR} ${UMPFACK_INCLUDE_DIR} )
	SET (LIBS ${LIBS} ${UMFPACK_LIBRARIES})
	SET (HAVE_UMFPACK TRUE)
ENDIF (UMFPACK_FOUND)

#
# Find optional OpenMP
#
IF (USE_OPENMP)
  FIND_PACKAGE(OpenMP)
  IF (OPENMP_FOUND)
    # UFCONFIG and AMD are dependencies
    MESSAGE (STATUS " -> OpenMP support enabled ")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
    SET (HAVE_OPENMP TRUE)
  ENDIF (OPENMP_FOUND)
ENDIF (USE_OPENMP)

if (USE_MARCHNATIVE)
   MESSAGE( STATUS "check if CMAKE_COMPILER_IS_GNUCC for USE_MARCHNATIVE")
   if (CMAKE_COMPILER_IS_GNUCC)
      MESSAGE( STATUS "yes, is gnu, use \"-march=native\" USE_MARCHNATIVE")
      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")
   endif()
endif (USE_MARCHNATIVE)

if (CMAKE_BUILD_TYPE MATCHES Debug)
   MESSAGE( STATUS "check if CMAKE_COMPILER_IS_GNUCC for extended warnings")
   if (CMAKE_COMPILER_IS_GNUCC)
      MESSAGE( STATUS "yes, is gnu, use \"-std=gnu89 -Wall -Wextra -Wno-comment -DFEINS_have_warning\"")
      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu89 -Wall -Wextra -Wno-comment -DFEINS_have_warning")	
   endif()
   MESSAGE( STATUS "defining DEBUGFEINS to enable debug parts of the code")
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEBUGFEINS")	
endif (CMAKE_BUILD_TYPE MATCHES Debug)


#
# Put information on optional libraries and configuration in config.h
#
SET ( INCLUDE_DIR ${INCLUDE_DIR} ${CMAKE_BINARY_DIR}/include )
CONFIGURE_FILE(${CMAKE_HOME_DIRECTORY}/config.h.in 
               ${CMAKE_BINARY_DIR}/include/config.h)


INCLUDE_DIRECTORIES(${INCLUDE_DIR})
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})

# display status message for important variables
MESSAGE( STATUS )
MESSAGE( STATUS "------------------------------------------------------------" )
MESSAGE( STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}" )
MESSAGE( STATUS "USE_OPENMP       = ${USE_OPENMP}" )
MESSAGE( STATUS "USE_MARCHNATIVE  = ${USE_MARCHNATIVE}" )
MESSAGE( STATUS "SUITESPARSE      = ${SUITESPARSE}" )
MESSAGE( STATUS "      use cmake -DSUITESPARSE=OFF to disable," )
MESSAGE( STATUS "       -DSUITESPARSE=/path/to/suitesparse to specify a path" )
MESSAGE( STATUS )
MESSAGE( STATUS "Change a value with: cmake -D<Variable>=<Value>" )
MESSAGE( STATUS "------------------------------------------------------------" )
MESSAGE( STATUS )

# force some variables that could be defined in the command line 
# to be written to cache
SET( CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
  "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE )
SET( USE_OPENMP "${USE_OPENMP}" CACHE BOOL 
  "Set to OFF to disable OpenMP supports" FORCE )
SET( USE_MARCHNATIVE "${USE_MARCHNATIVE}" CACHE BOOL 
  "Set to OFF to disable the optimization for current platform gcc only" FORCE )




#
# Specify sources
#



# Create a variable containing all non-problem specific .c files:
set(FeinsLib_SOURCES assembly.c cubature.c elements.c gen_aux.c
                     lin_solver.c linsolve_umfpack.c mesh.c
                     mesh_deform.c sparse.c) 



# Create variables containing problem specific .c files:
set(FeinsNavsto_SOURCES   navsto_adj.c navsto_aux.c navsto_solver.c
                          navsto_solver_bcontrol.c navstoassem.c
                          stokes_aux.c stokesassem.c) 
set(FeinsLame_SOURCES     lame_adj.c)
set(FeinsConvDiff_SOURCES assem_conv_diff.c)



# triangle/triangle.c needs special treatment, i.e. special FLAGS
set_property(
   SOURCE triangle/triangle.c
   APPEND PROPERTY COMPILE_DEFINITIONS TRILIBRARY 
   )


#
# Create the executable files from sources:
#

# test_assem
add_executable(test_assem test_assem.c
               ${FeinsLib_SOURCES} triangle/triangle.c)
target_link_libraries(test_assem ${LIBS})

# test_assem_t2
add_executable(test_assem_t2 test_assem_t2.c
               ${FeinsLib_SOURCES} triangle/triangle.c)
target_link_libraries(test_assem_t2 ${LIBS})

# test_sparse_cache_effects
add_executable(test_sparse_cache_effects test_sparse_cache_effects.c
               ${FeinsLib_SOURCES} triangle/triangle.c)
target_link_libraries(test_sparse_cache_effects ${LIBS})

# test_convection_diffusion
add_executable(test_convection_diffusion test_convection_diffusion.c 
               ${FeinsLib_SOURCES} ${FeinsConvDiff_SOURCES} 
               triangle/triangle.c )
target_link_libraries(test_convection_diffusion ${LIBS})

# test_conv_diff_bwEuler 
add_executable(test_conv_diff_bwEuler test_conv_diff_bwEuler.c 
               ${FeinsLib_SOURCES} ${FeinsConvDiff_SOURCES} 
               triangle/triangle.c )
target_link_libraries(test_conv_diff_bwEuler ${LIBS})

# test_conv_diff_ROS3P 
add_executable(test_conv_diff_ROS3P test_conv_diff_ROS3P.c 
               ${FeinsLib_SOURCES} ${FeinsConvDiff_SOURCES} 
               triangle/triangle.c )
target_link_libraries(test_conv_diff_ROS3P ${LIBS})



# test_lame
add_executable(test_lame test_lame.c 
               ${FeinsLib_SOURCES} ${FeinsLame_SOURCES} 
               triangle/triangle.c )
target_link_libraries(test_lame ${LIBS})

# test_lame_adj
add_executable(test_lame_adj test_lame_adj.c 
               ${FeinsLib_SOURCES} ${FeinsLame_SOURCES} 
               triangle/triangle.c )
target_link_libraries(test_lame_adj ${LIBS})


# test_mesh_deform
add_executable(test_mesh_deform test_mesh_deform.c 
               ${FeinsLib_SOURCES} 
               triangle/triangle.c )
target_link_libraries(test_mesh_deform ${LIBS})

# test_navsto_solver
add_executable(test_navsto_solver test_navsto_solver.c 
               ${FeinsLib_SOURCES} ${FeinsNavsto_SOURCES} 
               triangle/triangle.c )
target_link_libraries(test_navsto_solver ${LIBS})

# test_stokes2
add_executable(test_stokes2 test_stokes2.c 
               ${FeinsLib_SOURCES} ${FeinsNavsto_SOURCES} 
               triangle/triangle.c )
target_link_libraries(test_stokes2 ${LIBS})


# test_write_ssegs_svg
add_executable(test_write_ssegs_svg test_write_ssegs_svg.c 
               ${FeinsLib_SOURCES} triangle/triangle.c )
target_link_libraries(test_write_ssegs_svg ${LIBS})



