# Makefile for GNU-make
# INTEL Fortran: ifort 13.x to 19.x // 2023 to 2025
#
# É. Canot -- IPR/CNRS -- 20 Nov 2024
#
# this Makefile has no option. See the main Makefile.
#

include ../make_opt.inc

include ../Makefile.config

# configurable options (OS dependent)

# for optimization (both for ifort, icc, icpc)
OPT_FLAGS = # -O1 # -O3 -fp-model precise

#=======================================================================

# special tag : vendor / f90 abbrev
F90C_TAG=INTEL_IFC

# memorize MAKE local options
ifeq '$(CFG)' 'debug'
  MAKE_CFG=CFG=debug
else # 'release'
  MAKE_CFG=CFG=release
endif
ifeq '$(MEMTR)' 'yes'
  MAKE_MEMTR=MEMTR=yes
else
  ifeq '$(MEMTR)' 'full'
    MAKE_MEMTR=MEMTR=yes
    MEMTR_FULL=yes
  else
    MAKE_MEMTR=MEMTR=no
  endif
endif

# compiler -------------------------------------------------------------

F90C = $(F90_COMP)

# OpenMP flag (specific for each compiler)
OMP_FLAG = #-qopenmp

FPP_FLAGS = -D_$(F90C_TAG)

ifeq '$(CFG)' 'debug'

  CFG_FLAGS = -g -O0 -CB -traceback# -pg
  CFG_FLAGS_LIB_AUX = -g -O0 -CB -traceback# -pg
  LD_FLAGS =# -pg

else # 'release'

  FPP_FLAGS += -D_OPTIM
  CFG_FLAGS = $(OPT_FLAGS)
  CFG_FLAGS_LIB_AUX = $(OPT_FLAGS)
  LD_FLAGS =

endif

ifeq '$(NO_X11)' '"yes"'

  FPP_FLAGS += -D_NO_X11

endif

ifeq '$(DARWIN)' '"yes"'

  FPP_FLAGS += -D_DARWIN

endif

ifeq '$(HDF5)' '"yes"'

  FPP_FLAGS += -D_HDF5

endif

INCLUDES = -I../include

INCLUDES_DEV = -I../inc_dev

F90_FLAGS = $(INCLUDES) $(CFG_FLAGS) $(OMP_FLAG)

F90_FLAGS_DEV = $(INCLUDES_DEV) $(CFG_FLAGS) $(OMP_FLAG)

# the '-assume minus0' option allows the printing of the minus sign of
# zero (F95 standard).
# [option commented out on 2011-06-30, in order to check the validity
#  of numerical results among all the compilers used]
#F90_FLAGS += -assume minus0 $(OMP_FLAG)

F90_FLAGS_LIB_AUX = $(INCLUDES) $(CFG_FLAGS_LIB_AUX) $(OMP_FLAG)

LD_FLAGS += $(OMP_FLAG)

#----------------------------- libraries -------------------------------

ifeq '$(CFG)' 'debug'

  MUESLI_LIBS = ../lib/libfml.a

  ifeq '$(BLAS_LAPACK_VENDOR)' '"yes"'
    LAPACK_LIBS = -qmkl
  else
    ifeq '$(BLAS_LAPACK_ARCHIVED)' '"yes"'
      LAPACK_LIBS = $(LAPACK_DIR)/liblapack.a \
                    $(BLAS_DIR)/libblas.a \
                    $(ADD_LIB) $(LD_OPT)
    else
      LAPACK_LIBS = $(LAPACK_DIR)/liblapack.so \
                    $(BLAS_DIR)/libblas.so \
                    $(ADD_LIB)
    endif
  endif

  ifeq '$(HDF5)' '"yes"'
    HDF5_F90_LIBS = $(HDF5_F90_DIR)/libhdf5_fortran.a
  else
    HDF5_F90_LIBS =
  endif

else # 'release' (absolute path, comma after -rpath)
     # fix: doublequotes around `pwd` are required to take into account
     # some blanks in the path...

  MUESLI_LIBS = -Wl,-rpath,"`pwd`"/../lib -L"`pwd`"/../lib -lfml

  ifeq '$(BLAS_LAPACK_VENDOR)' '"yes"'
    LAPACK_LIBS = -qmkl
  else
    LAPACK_LIBS = -Wl,-rpath,$(LAPACK_DIR) $(LAPACK_DIR)/liblapack.so \
                  -Wl,-rpath,$(BLAS_DIR) $(BLAS_DIR)/libblas.so \
                  $(ADD_LIB)
  endif

  ifeq '$(HDF5)' '"yes"'
    HDF5_F90_LIBS = -Wl,-rpath,$(HDF5_F90_DIR) $(HDF5_F90_DIR)/libhdf5_fortran.so
  else
    HDF5_F90_LIBS =
  endif

endif

# PAPI (PerfCtr)
ifeq '$(PAPI)' 'yes'
  PAPI_LIBS = $(PAPI_DIR)/libpapi.a
else # linux kernel not patched with PERFCTR, or PAPI not installed
  PAPI_LIBS =
endif

 # recent READLINE library includes TERMCAP
ifeq '$(NEED_TERMCAP)' '"yes"'
  TERMCAP_LIB = -ltermcap
else
  TERMCAP_LIB =
endif

ifeq '$(HDF5)' '"yes"'
  HDF5_LIBS = -L$(HDF5_1_6) -lhdf5
else
  HDF5_LIBS =
endif

ZLIB_LIBS = -L$(ZLIB_DIR) -lz

ifeq '$(CFG)' 'debug'
  LIBS = obj/test_aux.o \
	 $(MUESLI_LIBS) $(LIBSTDC++) $(PAPI_LIBS) \
         $(LAPACK_LIBS) $(HDF5_F90_LIBS) $(HDF5_LIBS) $(ZLIB_LIBS) \
         $(TERMCAP_LIB)
else # mode OPTIM
  # most of external libraries are already linked in the shared versions of FML
  LIBS = obj/test_aux.o \
         $(MUESLI_LIBS) $(LIBSTDC++) \
         $(LAPACK_LIBS) \
         -lreadline
endif

ifeq '$(CFG)' 'debug'
  ifeq '$(NEED_LRT)' '"yes"'
    LIBS += -lrt
  endif
endif

#=======================================================================

PROGS = test_mod_physunits \
        test_mod_core \
        test_mod_sparse_1 \
        test_mod_sparse_2 \
        test_mod_elmat \
        test_mod_fileio \
        test_mod_elfun \
        test_mod_ops \
        test_mod_specfun \
        test_mod_datafun \
        test_mod_matfun_1 \
        test_mod_matfun_2 \
        test_mod_polyfun \
        test_mod_funfun

all : $(PROGS)

test_mod_core : obj/test_mod_core.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_sparse_1 : obj/test_mod_sparse_1.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_sparse_2 : obj/test_mod_sparse_2.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)


test_mod_fileio : obj/test_mod_fileio.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_elmat : obj/test_mod_elmat.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_elfun : obj/test_mod_elfun.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_specfun : obj/test_mod_specfun.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_ops : obj/test_mod_ops.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_datafun : obj/test_mod_datafun.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_matfun_1 : obj/test_mod_matfun_1.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_matfun_2 : obj/test_mod_matfun_2.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_polyfun : obj/test_mod_polyfun.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_funfun : obj/test_mod_funfun.o obj/lib_aux.o obj/funfun_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_physunits : obj/test_mod_physunits.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

test_mod_core_flops : obj/test_mod_core_flops.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ \
       obj/test_aux.o $(MUESLI_LIBS) $(LIBSTDC++) $(PAPI_REAL) $(LAPACK_LIBS) \
       $(HDF5_LIBS) $(ZLIB_LIBS) -lpthread \
       -lreadline -lhistory $(TERMCAP_LIB)

test_progress : obj/test_progress.o obj/lib_aux.o
	$(F90C) $(LD_FLAGS) -o $@ $^ $(LIBS)

obj/test_aux.o : test_aux.f90 ../lib/libfml.a ../include/fml.mod

obj/lib_aux.o : lib_aux.F90 ../lib/libfml.a ../include/fml.mod
	$(F90C) $(FPP_FLAGS) $(F90_FLAGS_LIB_AUX) -c $< -o $@

OBJ_DEP = obj/test_aux.o obj/lib_aux.o ../lib/libfml.a \
          ../include/fml.mod

obj/test_mod_core.o : test_mod_core.F90 $(OBJ_DEP)

obj/test_mod_sparse_1.o : test_mod_sparse_1.F90 $(OBJ_DEP)

obj/test_mod_sparse_2.o : test_mod_sparse_2.F90 $(OBJ_DEP)


obj/test_mod_fileio.o : test_mod_fileio.F90 $(OBJ_DEP)

obj/test_mod_elmat.o : test_mod_elmat.F90 $(OBJ_DEP)

obj/test_mod_elfun.o : test_mod_elfun.F90 $(OBJ_DEP)

obj/test_mod_specfun.o : test_mod_specfun.F90 $(OBJ_DEP)

obj/test_mod_ops.o : test_mod_ops.f90 $(OBJ_DEP)

obj/test_mod_datafun.o : test_mod_datafun.F90 $(OBJ_DEP)

obj/test_mod_matfun_1.o : test_mod_matfun_1.F90 $(OBJ_DEP)

obj/test_mod_matfun_2.o : test_mod_matfun_2.F90 $(OBJ_DEP)

obj/test_mod_polyfun.o : test_mod_polyfun.F90 $(OBJ_DEP)

obj/test_mod_funfun.o : test_mod_funfun.F90 $(OBJ_DEP) obj/funfun_aux.o

obj/test_mod_physunits.o : test_mod_physunits.f90 $(OBJ_DEP)

obj/test_mod_core_flops.o : test_mod_core_flops.f90 $(OBJ_DEP)

obj/test_progress.o : test_progress.f90 $(OBJ_DEP)

check : test_mod_core.dif \
        test_mod_sparse_1.dif \
        test_mod_sparse_2.dif \
        test_mod_fileio.dif \
        test_mod_elmat.dif \
        test_mod_elfun.dif \
        test_mod_specfun.dif \
        test_mod_ops.dif \
        test_mod_datafun.dif \
        test_mod_matfun_1.dif \
        test_mod_matfun_2.dif \
        test_mod_polyfun.dif \
        test_mod_funfun.dif \
        test_mod_physunits.dif

# *.dif must not depend on *.ref: the aim is to check new numerical
# results in comparing with old results.

%.dif : %
	./$< > $<.out 2>&1
ifeq '$(MEMTR)' 'yes'
	../bin/mem_debug_check < mem_debug.out > $<.mem_check.out
endif
	diff $<.ref $<.out > $<.dif || :
	@echo "  *** $* : checked ***"
	@echo

ifeq '$(MEMTR)' 'yes'

mem_check : test_mod_core.mem_check.out \
            test_mod_sparse_1.mem_check.out \
            test_mod_sparse_2.mem_check.out \
            test_mod_fileio.mem_check.out \
            test_mod_elmat.mem_check.out \
            test_mod_elfun.mem_check.out \
            test_mod_specfun.mem_check.out \
            test_mod_ops.mem_check.out \
            test_mod_datafun.mem_check.out \
            test_mod_matfun_1.mem_check.out \
            test_mod_matfun_2.mem_check.out \
            test_mod_polyfun.mem_check.out \
            test_mod_funfun.mem_check.out \
            test_mod_physunits.mem_check.out

%.mem_check.out : %
	./$< > /dev/null 2> mem_debug.out
	../bin/mem_debug_check < mem_debug.out > $@

else

mem_check :
	@echo
	@echo "  *** you must use the 'MEMTR=' option with 'yes' or 'full' ***"
	@echo

endif

#-------------------------------- rules --------------------------------

.SUFFIXES :
.SUFFIXES : .F90 .f90 .o

obj/%.o : %.F90
	$(F90C) $(FPP_FLAGS) $(F90_FLAGS) -c $< -o $@

obj/%.o : %.f90
	$(F90C) $(F90_FLAGS) -c $< -o $@

clean :
	rm -f obj/* *.mod make_options \
	      *_tmp.* *.c *.out *.res *.dif \
         mem_debug.out

distclean : clean
	rm -f $(PROGS) \
	      test_mod_core_flops \
	      test_progress \
	      exam_traceback
