###
#
#  @copyright 2017-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
#                       Univ. Bordeaux. All rights reserved.
#
#  @version 6.4.0
#  @author Mathieu Faverge
#  @author Pierre Ramet
#  @author Tony Delarue
#  @author Nolan Bredel
#  @date 2024-07-05
#
###
cmake_minimum_required (VERSION 3.5)
cmake_policy(SET CMP0054 NEW)

### CTest execution
set( PASTIX_DRIVERS
  # reentrant fails with Scotch parser !
  analyze simple simple_solve_and_refine simple_trans step-by-step schur personal reentrant multidof ) # old/old_simple old/old_step-by-step
set( PASTIX_TESTS
  simple )
set( PASTIX_REFINE
  refinement )
set( PASTIX_MIXED
  simple )
set( PASTIX_ALLOC
  simple step-by-step )
set( PASTIX_FACTO
  0 1 2 ) # LLh, LDLt, LU
set( PASTIX_SCHEDS
  0 1 4 ) # sequential, static, dynamic
set( PASTIX_COMPRESS_METHOD
  svd
  pqrcp
  rqrcp
  tqrcp
  rqrrt )
set( PASTIX_SPLIT_METHOD
  not
  kway
  kwayprojections )
set( RUNTYPE shm )
set( PASTIX_ORDER )

set( _complex   c z )
set( _factodiag 1 3 4 )

# Add runtimes
if (PASTIX_WITH_PARSEC)
  list( APPEND PASTIX_SCHEDS 2 ) # parsec
endif (PASTIX_WITH_PARSEC)
if (PASTIX_WITH_STARPU)
  list( APPEND PASTIX_SCHEDS 3 ) # starpu
endif (PASTIX_WITH_STARPU)

# Add runtype
if( PASTIX_WITH_MPI )
  list( APPEND RUNTYPE mpi_rep mpi_dst )
endif()

# Add orderings
if (PASTIX_ORDERING_SCOTCH)
  list( APPEND PASTIX_ORDER scotch )
endif (PASTIX_ORDERING_SCOTCH)
if (PASTIX_ORDERING_PTSCOTCH)
  list( APPEND PASTIX_ORDER ptscotch )
endif (PASTIX_ORDERING_PTSCOTCH)
if (PASTIX_ORDERING_METIS)
  list( APPEND PASTIX_ORDER metis )
endif (PASTIX_ORDERING_METIS)

foreach( version ${RUNTYPE} )
  set( exe "" )
  set( opt "" )
  if( NOT version STREQUAL "shm" )
    set( exe ${pastix_mpiexec} )
    if( version STREQUAL "mpi_dst" )
      set( opt "-a 1" )
    endif()
  endif()

  ### All drivers with Laplacian and default parameters
  foreach(example ${PASTIX_DRIVERS} )
    foreach(arithm ${PASTIX_PRECISIONS} )
      set(factos ${PASTIX_FACTO})
      if (arithm IN_LIST _complex)
        list(APPEND factos 3 4)
      endif()
      foreach(facto ${factos} )
        set( _test_name c_${version}_example_${example}_lap_${arithm}_facto${facto} )
        set( _test_cmd  ${exe} ./${example} ${opt} -9 ${arithm}:10:10:10:2 -f ${facto} )
        # Let's avoid testing with diagonal factorizations and Schur complement
        if ( NOT((facto IN_LIST _factodiag) AND (example STREQUAL "schur")) )
          if (example STREQUAL "multidof")
            if ( arithm EQUAL d )
              add_test(${_test_name}_fix ${_test_cmd} -c 2)
              add_test(${_test_name}_var ${_test_cmd} -c 5)
            endif()
          else()
            if( NOT ((NOT version STREQUAL "shm") AND ((example STREQUAL "reentrant") OR (example STREQUAL "schur"))) )
              add_test(${_test_name} ${_test_cmd} -c 2 )
            endif()
          endif()
        endif()
      endforeach()
    endforeach()
  endforeach()

  ### Driver / order
  foreach(example ${PASTIX_TESTS} )
    foreach(order ${PASTIX_ORDER} )
      set( _test_name c_${version}_example_${example}_${order} )
      set( _test_cmd  ${exe} ./${example} ${opt} -o ${order} )

      # RSA
      add_test(${_test_name}_rsa ${_test_cmd} --rsa ${CMAKE_SOURCE_DIR}/test/matrix/small.rsa  -f 1 -d dparm_epsilon_magn_ctrl 1e-14)
      # Matrix Market
      add_test(${_test_name}_mm  ${_test_cmd} --mm  ${CMAKE_SOURCE_DIR}/test/matrix/young4c.mtx  -f 1)
      # Harwell Boeing
      add_test(${_test_name}_hb  ${_test_cmd} --hb  ${CMAKE_SOURCE_DIR}/test/matrix/orsirr.rua   -f 2)
      # Matrix Market - Hermitian
      add_test(${_test_name}_mm2 ${_test_cmd} --mm  ${CMAKE_SOURCE_DIR}/test/matrix/mhd1280b.mtx -f 2 -d dparm_epsilon_magn_ctrl 1e-14 )
    endforeach()
  endforeach()

  ### Single Allocation
  foreach(example ${PASTIX_ALLOC} )
    set( _test_name c_${version}_example_${example}_single )
    set( _test_cmd  ${exe} ./${example} ${opt} )

    # RSA
    add_test(${_test_name}_rsa ${_test_cmd} --rsa ${CMAKE_SOURCE_DIR}/test/matrix/small.rsa  -f 1 -d dparm_epsilon_magn_ctrl 1e-14 -i iparm_global_allocation 1)
    # Matrix Market
    add_test(${_test_name}_mm  ${_test_cmd} --mm  ${CMAKE_SOURCE_DIR}/test/matrix/young4c.mtx  -f 1 -i iparm_global_allocation 1)
    # Harwell Boeing
    add_test(${_test_name}_hb  ${_test_cmd} --hb  ${CMAKE_SOURCE_DIR}/test/matrix/orsirr.rua   -f 2 -i iparm_global_allocation 1)
    # Matrix Market - Hermitian
    add_test(${_test_name}_mm2 ${_test_cmd} --mm  ${CMAKE_SOURCE_DIR}/test/matrix/mhd1280b.mtx -f 2 -d dparm_epsilon_magn_ctrl 1e-14 -i iparm_global_allocation 1)
  endforeach()

  ### Refinement
  foreach(example ${PASTIX_TESTS} )
    set( _test_name c_${version}_example_${example}_refine )
    set( _test_cmd  ${exe} ./${example} ${opt} )

    add_test(${_test_name}_cg       ${_test_cmd} --hb ${CMAKE_SOURCE_DIR}/test/matrix/small.rsa  -f 1 -i iparm_refinement pastixrefinecg -d dparm_epsilon_magn_ctrl 1e-14)
    add_test(${_test_name}_gmres    ${_test_cmd} --hb ${CMAKE_SOURCE_DIR}/test/matrix/orsirr.rua -f 2 -i iparm_refinement pastixrefinegmres)
    add_test(${_test_name}_bicgstab ${_test_cmd} --hb ${CMAKE_SOURCE_DIR}/test/matrix/orsirr.rua -f 2 -i iparm_refinement pastixrefinebicgstab)
  endforeach()

  ### Refinement with Laplacian and default parameters
  foreach(example ${PASTIX_REFINE} )
    foreach(arithm ${PASTIX_PRECISIONS} )
      set( _test_name c_${version}_example_${example}_lap_${arithm}_refine )
      set( _test_cmd_her  ${exe} ./${example} ${opt} -x ${arithm}:10:10:10:2 )
      set( _test_cmd_sym  ${exe} ./${example} ${opt} -9 ${arithm}:10:10:10:2 )
      if (arithm IN_LIST _complex)
        add_test(${_test_name}_cg_her       ${_test_cmd_her} -i iparm_refinement pastixrefinecg)
        add_test(${_test_name}_gmres_her    ${_test_cmd_her} -i iparm_refinement pastixrefinegmres)
        add_test(${_test_name}_bicgstab_her ${_test_cmd_her} -i iparm_refinement pastixrefinebicgstab)
      endif()
      add_test(${_test_name}_cg_sym       ${_test_cmd_sym} -i iparm_refinement pastixrefinecg)
      add_test(${_test_name}_gmres_sym    ${_test_cmd_sym} -i iparm_refinement pastixrefinegmres)
      add_test(${_test_name}_bicgstab_sym ${_test_cmd_sym} -i iparm_refinement pastixrefinebicgstab)
    endforeach()
  endforeach()

  ### MIXED Precision
  foreach(example ${PASTIX_MIXED} )
    set( _test_name c_${version}_example_${example}_mixed_refine )
    set( _test_cmd  ${exe} ./${example} ${opt} -i iparm_mixed 1 )
    add_test(${_test_name}_cg       ${_test_cmd} --hb ${CMAKE_SOURCE_DIR}/test/matrix/small.rsa  -f 1 -i iparm_refinement pastixrefinecg -d dparm_epsilon_magn_ctrl 1e-14 -d dparm_epsilon_refinement 1e-7)
    add_test(${_test_name}_gmres    ${_test_cmd} --hb ${CMAKE_SOURCE_DIR}/test/matrix/orsirr.rua -f 2 -i iparm_refinement pastixrefinegmres)
    add_test(${_test_name}_bicgstab ${_test_cmd} --hb ${CMAKE_SOURCE_DIR}/test/matrix/orsirr.rua -f 2 -i iparm_refinement pastixrefinebicgstab)
    set( PASTIX_MIXED_PRECISION d z )
    foreach( arithm_mixed ${PASTIX_MIXED_PRECISION} )
      set(factos ${PASTIX_FACTO})
      if (arithm_mixed IN_LIST _complex)
        list(APPEND factos 3 4)
      endif()
      foreach(facto ${factos} )
        set( _test_name c_${version}_example_${example}_mixed_lap_${arithm_mixed}_facto${facto} )
        set( _test_cmd2  ${_test_cmd} -9 ${arithm_mixed}:10:10:10:2 -f ${facto} )
        if( version STREQUAL "shm" )
          add_test(${_test_name} ${_test_cmd2} -c 2 )
        endif()
      endforeach()
      set( _test_name c_${version}_example_${example}_mixed_lap_${arithm_mixed}_refine )
      set( _test_cmd_her  ${_test_cmd} -x ${arithm_mixed}:10:10:10:2 )
      set( _test_cmd_sym  ${_test_cmd} -9 ${arithm_mixed}:10:10:10:2 )
      if (arithm_mixed IN_LIST _complex)
        add_test(${_test_name}_cg_her       ${_test_cmd_her} -i iparm_refinement pastixrefinecg)
        add_test(${_test_name}_gmres_her    ${_test_cmd_her} -i iparm_refinement pastixrefinegmres)
        add_test(${_test_name}_bicgstab_her ${_test_cmd_her} -i iparm_refinement pastixrefinebicgstab)
      endif()
      add_test(${_test_name}_cg_sym       ${_test_cmd_sym} -i iparm_refinement pastixrefinecg)
      add_test(${_test_name}_gmres_sym    ${_test_cmd_sym} -i iparm_refinement pastixrefinegmres)
      add_test(${_test_name}_bicgstab_sym ${_test_cmd_sym} -i iparm_refinement pastixrefinebicgstab)
    endforeach()
  endforeach()

  ### distributed mpi does not work with StarPU and Parsec
  set( schedulers ${PASTIX_SCHEDS} )
  if ( ${version} STREQUAL "mpi_dst" )
    remove( schedulers 2 )
  endif()

  ### Scheduling
  foreach( example ${PASTIX_TESTS} schur )
    foreach( scheduler ${schedulers} )
      foreach( arithm ${PASTIX_PRECISIONS} )
        set(factos ${PASTIX_FACTO})
        if (arithm IN_LIST _complex)
          list(APPEND factos 3 4)
        endif()
        foreach( facto ${factos} )
          if ( (example STREQUAL "schur") AND ((facto IN_LIST _factodiag) OR (NOT version STREQUAL "shm")) )
            continue()
          endif()
          set( _test_name ${version}_example_${example}_lap_${arithm}_facto${facto}_sched${scheduler} )
          set( _test_cmd  ${exe} ./${example} ${opt} -9 ${arithm}:10:10:10:2 -s ${scheduler} -f ${facto} )
          # 1D
          add_test(${_test_name}_1d  ${_test_cmd} -i iparm_tasks2d_level 0)
          if ((scheduler EQUAL 2) OR (scheduler EQUAL 3))
            # 2D
            add_test(${_test_name}_2d   ${_test_cmd} -i iparm_tasks2d_width 0)
            # 1D/2D
            add_test(${_test_name}_1d2D ${_test_cmd} -i iparm_tasks2d_width 16)
          endif()
          # left looking
          if (scheduler EQUAL 3)
            add_test(${_test_name}_1d_ll   ${_test_cmd} -i iparm_tasks2d_level 0  -i iparm_facto_look_side 0)
            add_test(${_test_name}_2d_ll   ${_test_cmd} -i iparm_tasks2d_width 0  -i iparm_facto_look_side 0)
            add_test(${_test_name}_1d2D_ll ${_test_cmd} -i iparm_tasks2d_width 16 -i iparm_facto_look_side 0)
          endif()
        endforeach()
      endforeach()
    endforeach()
  endforeach()

  ### We do not need to test these configurations in both replicated
  ### and distributed mpi cases for internal schedulers.
  if ( ${version} STREQUAL "mpi_rep" )
    set( schedulers ${PASTIX_SCHEDS} )
    remove( schedulers 0 1 4 )
  endif()

  ### Low Rank
  foreach(example ${PASTIX_TESTS} )
    foreach(scheduler ${schedulers} )
      if( (NOT version STREQUAL "shm") AND ((scheduler EQUAL 2)) )
        continue()
      endif()
      foreach(arithm ${PASTIX_PRECISIONS} )
        if (arithm IN_LIST _complex)
          list(APPEND factos 3 4)
        endif()
        set(factos ${PASTIX_FACTO})
        if (arithm IN_LIST _complex)
          list(APPEND factos 3 4)
        endif()
        foreach(facto ${factos} )
          foreach(method ${PASTIX_COMPRESS_METHOD} )
            foreach(split ${PASTIX_SPLIT_METHOD} )
              set( _lowrank_params -i iparm_compress_min_width 16 -i iparm_compress_min_height 16 -i iparm_splitting_strategy pastixsplit${split} -i iparm_compress_method pastixcompressmethod${method} )
              set( _test_name ${version}_example_${example}_lap_${arithm}_facto${facto}_sched${scheduler}_${split}_${method} )
              set( _test_cmd  ${exe} ./${example} ${opt} -9 ${arithm}:10:10:10:2 -s ${scheduler} -f ${facto} ${_lowrank_params} )

              # Begin
              add_test(${_test_name}begin ${_test_cmd} -i iparm_compress_when pastixcompresswhenbegin)
              add_test(${_test_name}end   ${_test_cmd} -i iparm_compress_when pastixcompresswhenend  )
              # End
            endforeach()
          endforeach()

          set( split  kway  )
          set( method pqrcp )
          set( _lowrank_params -i iparm_compress_min_width 16 -i iparm_compress_min_height 16 -i iparm_splitting_strategy pastixsplit${split} -i iparm_compress_method pastixcompressmethod${method} )
          set( _test_name ${version}_example_${example}_lap_${arithm}_facto${facto}_sched${scheduler}_${split}_${method} )
          set( _test_cmd  ${exe} ./${example} ${opt} -9 ${arithm}:10:10:10:2 -s ${scheduler} -f ${facto} ${_lowrank_params} )
          add_test(${_test_name}ilu0  ${_test_cmd} -i iparm_compress_when pastixcompresswhenbegin -i iparm_compress_iluk 0)
          add_test(${_test_name}ilu1  ${_test_cmd} -i iparm_compress_when pastixcompresswhenbegin -i iparm_compress_iluk 1)
        endforeach()
      endforeach()
    endforeach()
  endforeach()
endforeach()
