!compKv1 = V_activate, compKv2 = V_inactivate
!*****************
! File Description:  
!   Full EC coupling whole-cell model
! Creator: Hoang-Trong Minh Tuan 
! 
! Rev: 0.1
! Update: 
!    1.0: major revision (new algorithm, new parameter files) (March, 2nd, 2012 - Tuan)
!*******************/

PROGRAM SparkCode_GPU
  USE precisioninfo
  USE makeKs_utility
  USE data_global
  USE data_ecc
  USE error_codes
  USE hdf5
  USE ecc_gpu_utility
  USE cudafor
  IMPLICIT NONE
#include "macro.h"

  INTEGER :: ierr
  INTEGER :: hdf_error
  INTEGER :: version_info(3)
  INTEGER(2) :: ic2, cmax2
  INTEGER(4) :: ic4, cmax4
  REAL :: crate2, crate4

  ierr = SUCCESS

!!  CALL export_Umat(49, 2)
!!$  CALL state_breakdown(50, 20, ierr, hdf_error)
!!$  PRINT *, ierr, hdf_error
!!$  PRINT *, state_combine_single(ierr, hdf_error, 20)
!!$  stop
!     PRINT *, "HELLO" 
  CALL check_expiration()
     PRINT *, "AFTER check_expiration()"
  CALL H5get_libversion_f(version_info(1), version_info(2), version_info(3), hdf_error)
  WRITE(*,"(A i0 '.' i0 '.' i0)") "HDF5 version:", version_info
     PRINT *, "AFTER H5get_libversion_f()"
  CALL SYSTEM_CLOCK(ic2, crate2, cmax2)  !for benchmarking purpose
     PRINT *, "AFTER SYSTEM_CLOCK()"
  ierr =  prog_get_info()
  IF (ierr .NE. SUCCESS) THEN
     CALL cleanup()
  END IF
     PRINT *, "BEFORE check_ecc_data()"
  ierr = check_ecc_data()
     PRINT *, "AFTER check_ecc_data()"
  IF (ierr .NE. SUCCESS) THEN
     CALL cleanup()
  END IF
  ierr = init_GPU(gpuID)
     PRINT *, "AFTER init_GPU()"
  IF (ierr .NE. SUCCESS) THEN
     PRINT *, "inside the IF(ierr .NE. SUCCESS) statement before cleanup()"
    CALL cleanup()
     PRINT *, "after cleanup()"

  END IF
!!$  PRINT *, "g_bCa", find_bg_Ca_conductance()
!!$  stop
!!$  PRINT *, "v_ryr_T", find_v_ryr(0.22d0, V_myo_T, 20000, N_R)
!!$  stop
  PRINT *, "before setup_RYR"
  ierr =  setup_RyR(ryr_Kcal_act_mode1, ryr_Kfree_mode1,ryr_Kcal_act_mode2, ryr_Kfree_mode2, ryr_Kfree, &
       ryr_KRos, N_R, mR, iU_R, ryr_compKcal_act_mode1, ryr_compKfree_mode1,ryr_compKcal_act_mode2, ryr_compKfree_mode2, &
       ryr_compKfree, ryr_compKRos, ryr_indxKcal_act_mode1, ryr_indxKfree_mode1, ryr_indxKcal_act_mode2, &
       ryr_indxKfree_mode2, ryr_indxKfree, ryr_indxKRos, U_Ro, U_RyR_State, ryr_Ncol_Kcal_act_mode1, ryr_Ncol_Kfree_mode1, &
       ryr_Ncol_Kcal_act_mode2, ryr_Ncol_Kfree_mode2, ryr_Ncol_Kfree, ryr_Ncol_KRos, irow_R)
  IF (ierr .NE. SUCCESS) THEN
     CALL cleanup()
  END IF

!  PRINT *, "after setup_RYR"
!  PRINT *, "ryr_Kcal_act_mode1: "
!  CALL print_mat(ryr_Kcal_act_mode1,4,4)
!  PRINT *, "ryr_Kcal_act_mode2: "
!  CALL print_mat(ryr_Kcal_act_mode2,4,4)
!  WRITE(100,*) "ryr_compKcal_act_mode1: ", ryr_compKcal_act_mode1
!  CALL print_mat(ryr_compKcal_act_mode1,irow_R,3,'ryr_compKcal_act_mode1.txt')
!  CALL print_mat(ryr_compKcal_act_mode2,irow_R,3,'ryr_compKcal_act_mode2.txt')
!  WRITE(200,*) "ryr_compKcal_act_mode2: ", ryr_compKcal_act_mode2
!  PRINT *, "ryr_compKcal_act_mode1: ", ryr_compKcal_act_mode1
!  PRINT *, "ryr_compKcal_act_mode2: ", ryr_compKcal_act_mode2

  ierr = setup_LCC(lcc_Kv_act, lcc_Kv_inact, lcc_KCal_inact, lcc_Kfree, N_L, mL, iU_L, lcc_compKv_act, lcc_compKv_inact, &
       lcc_compKcal_inact, lcc_compKfree, &
       lcc_indxKv_act, lcc_indxKv_inact, lcc_indxKcal_inact, lcc_indxKfree, &
       U_Lo, lcc_Ncol_Kv_act, lcc_Ncol_Kv_inact, lcc_Ncol_Kcal_inact, lcc_Ncol_Kfree, irow_L)
  IF (ierr .NE. SUCCESS) THEN
     CALL cleanup()
  END IF
  PRINT *, "after setup_LCC"
!!$  ierr = makeKs_nj(ryr_KCal_act, ryr_Kfree, mR, iU_R, ryr_initialstate, &
!!$       lcc_Kv_act, lcc_Kv_inact, lcc_KCal_inact, lcc_Kfree, mL, iU_L, lcc_initialstate, &
!!$       aKv1_nj, aKv2_nj, aKm1_nj, aKp1_nj,&
!!$          aKm2_nj, aKp2_nj, U_Lo_nj, U_Ro_nj, pL_nj, pR_nj, irow_L_nj, irow_R_nj)
!!$  IF (ierr .NE. SUCCESS) THEN
!!$     CALL cleanup()
!!$  END IF

#if _TEST_ORPHAN_CRU_ == _YES
  CALL makeKs_orphan_2(N_R, aKm2_orphan, aKp2_orphan, U_Ro_orphan, irow_R_orphan)
!!$  CALL print_mat(U_Ro_orphan, irow_R_orphan, 1)
!!$  PRINT *, U_Ro_orphan(1:irow_R_orphan)
!!$ STOP
#endif  
  PRINT *,"Ca_myo: ",Ca_myo
  PRINT *, "before init_Simulation"
  ierr = init_Simulation()
  PRINT *,"Ca_myo after init Simulation: ",Ca_myo
  IF (ierr .NE. SUCCESS) THEN
     CALL cleanup()
  END IF
  PRINT *, "init_Simulation() completed"
  CALL continue_Simulation()
  PRINT *,"Ca_myo: ",Ca_myo
  PRINT *, "after continue_Simulation()"
  CALL finalize_Simulation()

  CALL SYSTEM_CLOCK(count=ic4)
  WRITE(log_string, *)  "the elapsed time (sec) is ", DBLE((ic4-ic2))/crate2
  CALL write2log(log_string)
  
  !free
  CALL program_cleanup()
CONTAINS
  SUBROUTINE program_cleanup()
    CALL cleanup_data_ecc()
    CALL gpu_cleanup()
    CALL cleanup()
  END SUBROUTINE program_cleanup
END PROGRAM SparkCode_GPU
 
