#!/bin/bash

-include ${AMUSE_DIR}/config.mk

# NOTE: MESA is no longer supported on 32-bit systems.  This isn't by design;
# we simply haven't been able to get it to work!  So if you really-really want 
# to use an antique 32-bit system for mesa, you'll have to try to make it work yourself.
# But I think you'd be better off switching to a 64-bit machine.

# Step 0) Check if you have set the correct environment variables
ifndef MESA_DIR
ifndef MESA_DIR_INTENTIONALLY_EMPTY
$(error MESA_DIR enviroment variable is not set)
endif
endif

# step 1) specify your compilers

# NOTE: recent versions of mesa have required reduced optimization 
# in order to work with ifort; we suggest using gfortran instead of ifort if possible.

CC = $(MPICC)
FC =  $(MPIFC)

# Set optimization level
ARCH = $(shell uname -m)

ifeq (${ARCH},x86_64)
OPT_LEVEL = 2
else ifeq (${ARCH},aarch64)
OPT_LEVEL = 2
SPECIAL_FC_FLAGS := ${SPECIAL_FC_FLAGS} -ffp-contract=off
else
OPT_LEVEL = 0
endif


# if you need special flags for the compiler, define them here:
SPECIAL_FC_FLAGS = $(CFLAGS)
SPECIAL_C_FLAGS = $(FCFLAGSs)

# step 1.a) [temporary workaround for loader problem on Mac:] 
#           go down to select the correct entry for LOAD_MATRIX 
#           depending on whether you are on Linux or Mac 

# step 2) specify whether to use crmth for math library

USE_CRMATH = YES

ifeq ($(USE_CRMATH),YES)
LOAD_CRMATH = -L$(MESA_DIR)/lib -lcrmath -lcrlibm
export MESASDK_MATH_SLOT = crmath
INCLUDE_CRMATH = -I$(MESA_DIR)/include
endif

# step 3) specify which BLAS and LAPACK libraries to use for mesa/mtx

# these are the standard defaults
WHICH_LAPACK = 
LOAD_LAPACK = $(LAPACK_LIBS) -llapack95
WHICH_BLAS = 
LOAD_BLAS = $(BLAS_LIBS) $(LAPACK_LIBS) -llapack95
MKL_INCLUDE = 

# step 4) do you want to use PGPLOT with mesa/star?                                                                                     
# you can have onscreen plots updated at each step,                                                                                     
# and you can save files for making movies.  very cool!                                                                                 

# NOTE: you need to have a PGPLOT built using the same fortran and c compiler as you                                                    
# are using for mesa.                                                                                                                   

# if you don't already have a compatible pgplot,                                                                                         
# follow the instructions in pgplot/README                                                                                               

# to access pgplot from mesa/star,                                                                                                       
# set USE_PGSTAR = YES and set LOAD_PGPLOT to load the libraries.                                                                       
# in mesa/star, set the control parameter pgstar_flag = .true. in &star_job                                                             
# when you run star it will open a window using X and draw plots using PGSTAR                                                           
# the plots will be updated each time a log entry is made.                                                                               
# see star/test/src/pgstar_defaults.dek for details.                                                                                     

# NOTE: if you have libpng, then include '-lpng' in the LOAD_PGPLOT line.                                                               
# the *.png files are excellent for making movies.                                                                                       
# but if you don't have libpng and can't get it, no problem; it isn't required.                                                         
# just remove '-lpng' from the LOAD_PGPLOT line.                                                                                         

# Similarly, if you don't have X windows and don't want to make onscreen plots,                                                         
# then you can load PGPLOT without it.  Just delete the X stuff from LOAD_PGPLOT.                                                       

# for users of Red Hat OS: Georgios Magkotsios reports success with these settings:                                                     
#LOAD_PGPLOT = -L${PGPLOT_DIR} -lpgplot -L/usr/lib64 -lX11 -lsvml -lpng                                                                 
#FCstatic = -shared-intel #-Bstatic -static-intel                                                                                       

# for Ubuntu, Philip Pinto found these libraries to be necessary:                                                                       
#LOAD_PGPLOT = -L${PGPLOT_DIR} -lpgplot  -lX11 -lxcb -lXau -lXdmcp -lXext -lpng -lz                                                    

# for Fedora 12 (x86_64), Mike Zingale reported that the following worked                                                               
# 1. at the terminal:                                                                                                                   
#  yum install pgplot pgplot-devel                                                                                                       
# 2. in the mesa/util/makefile_header                                                                                                   
# USE_PGSTAR = YES                                                                                                                       
# LOAD_PGPLOT = -lpgplot -L/usr/lib64 -lX11 -lpng                                                                                       
# 3. it is also important that the following environment variable be set:                                                               
# export PGPLOT_DIR=/usr/share/pgplot/  


# NOTE: a change in USE_PGSTAR doesn't take effect until you next recompile mesa/star

# for now, GYRE is only available with the mesasdk 
USE_GYRE = YES

# See http://www.gnu.org/software/make/manual/make.html#Testing-Flags for findstring
ifneq (,$(findstring ifort,$(FC)))

USE_PGSTAR = NO
LOAD_PGPLOT = 

#USE_PGSTAR = YES
#LOAD_PGPLOT = -L/Users/bpaxton/mesa/utils/pgplot -lpgplot -L/usr/X11R6/lib -lX11 -lpng
#LOAD_PGPLOT = -L/rpod2/opt/pgplot -lpgplot -L/usr/X11R6/lib -lX11 -lpng

else
ifneq (,$(findstring gfortran,$(FC)))

#USE_PGSTAR = NO
#LOAD_PGPLOT = 
USE_PGSTAR = NO
LOAD_PGPLOT = 

else

USE_PGSTAR = NO
LOAD_PGPLOT = 

endif
endif





# step 5) Load options for HDF5, this must be compiled with the same compilier as mesa

# To install hdf5 in $MESA_DIR/utils with ifort run:
#export CC=icc
#export F9X=ifort
#export CXX=icpc
#export VERSION=1.8.17
#cd $MESA_DIR/utils
#rm -rf hdf5* 2>/dev/null
#wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-${VERSION%.*}/hdf5-"$VERSION"/src/hdf5-"$VERSION".tar.bz2
#tar xvf hdf5-"$VERSION".tar.bz2
#cd hdf5-"$VERSION"
#CCFLAGS=-D_Float128=__float128 FCFLAGS="-D_Float128=__float128" ./configure --enable-fortran --enable-fortran2003
#make
#make install
#cd $MESA_DIR

#
#
# and set in this makefile
# LOAD_HDF5 = -L${MESA_DIR}/utils/hdf5/lib -lhdf5_fortran -lhdf5 -lz
# INCLUDE_HDF5 = -I${MESA_DIR}/utils/hdf5/include
#
# And in your shell
# export LD_LIBRARY_PATH=$MESA_DIR/utils/hdf5/lib:$LD_LIBRARY_PATH

# These are if you are using the sdk hdf5 implementation
LOAD_HDF5 = -L${MESA_DIR}/lib -ldl -lhdf5_fortran -lhdf5 -lz
INCLUDE_HDF5 = -I${MESA_DIR}/include

# If not YES then we don't use HDF5, thus you wont have access to custom weak rates
# Also the rates test suite will not pass so do: /usr/bin/touch $MESA_DIR/rates/skip_test
# if you change this option
USE_HDF5 = YES


# step 6) now do the mesa install
ifeq ($(OPENMP_ENABLED), yes)
USE_OPENMP = YES
else
USE_OPENMP = NO
endif

# step 7) Build shared libraries? Needed if you want mesa to be usable in python

USE_SHARED = NO

# do install at the top level mesa directory

# NOTE: do NOT run the install scripts at the subdirectory level
# those are for use by the top level script

# Unless you are adding a new compiler to the list of options,
# you shouldn't need to change any of the following stuff.
# It simply defines things for use by the module makefiles.


# ifneq (,$(findstring ifort,$(FC)))

# #FCbasic = $(SPECIAL_FC_FLAGS) -assume protect-parens -fp-model source -prec-div -prec-sqrt -ftz -traceback -error-limit 6
# FCbasic = $(SPECIAL_FC_FLAGS) -assume protect-parens -fp-model source -prec-div -prec-sqrt -traceback -error-limit 6

# # use -vec-report2 to check on vectorization

# FCimpno = -implicitnone 
# FCchecks = -check uninit -check pointers -check bounds -check all
# FCwarn = -warn all -warn nounused
# FCwarn_unused = -warn unused
# FC_fixed_preprocess = -fpp
# FC_free_preprocess = -fpp
# FCfixed = -fixed -132 $(FC_fixed_preprocess)
# FCfixed72 = -fixed $(FC_fixed_preprocess)
# FCfree = -free $(FC_free_preprocess)
# FCopt = -O1
# FCdebug = 
# SLOW_COMPILE = 
# OPENMP_FCFLAGS ?= -openmp
# ifeq ($(USE_OPENMP),YES)
# FCopenmp = -g $(OPENMP_FCFLAGS) -threads
# else
# FCopenmp = 
# endif
# FCstatic =

# else
# ifneq (,$(findstring gfortran,$(FC)))

SKIP_NAN_TRAPS = YES

FCbasic = -Wno-uninitialized -fno-range-check -fmax-errors=100 $(SPECIAL_FC_FLAGS) $(FCbasic2)
FCbasic2 = -fprotect-parens -fno-sign-zero -fbacktrace -ggdb -finit-real=snan
# -Warray-temporaries
 
FCstandard = -std=f2008 -Wno-error=tabs

FCimpno = -fimplicit-none  
FCchecks = -fbounds-check
FCwarn = -Wunused-value -W -Wno-compare-reals -Wno-unused-parameter -Wno-function-elimination
#FCwarn = -Wunused-value -Werror -W -Wno-compare-reals -Wno-unused-parameter
 
FC_fixed_preprocess = -x f77-cpp-input
FC_free_preprocess = -x f95-cpp-input
FCfixed = -ffixed-form -ffixed-line-length-none $(FC_fixed_preprocess)
FCfixed72 = -ffixed-form $(FC_fixed_preprocess)
FCfree = -ffree-form -ffree-line-length-none $(FC_free_preprocess)
FCopt = -O${OPT_LEVEL} -ftree-vectorize
FCdebug = -ggdb
FCstatic =
SLOW_COMPILE = -fno-var-tracking
OPENMP_FCFLAGS ?= -fopenmp
ifeq ($(USE_OPENMP),YES)
FCopenmp = $(OPENMP_FCFLAGS)
else
FCopenmp = 
endif

# else

# FCbasic = UNKNOWN COMPILER
# FCchecks =
# FCwarn = 
# FCfixed =
# FCfree =
# FCopt = 
# FCdebug = 
# FCopenmp = 
# SLOW_COMPILE = 
# endif
# endif

LIB_TOOL_STATIC = ar crs
LIB_SUFFIX_STATIC = a

# Flags needed for shared libraries
ifeq ($(USE_SHARED), YES)
   UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
   MD := $(shell realpath $(MESA_DIR)/lib)
   # Rpaths need to resolve relative to module/test folder plus the final location of the library
   LIB_FLAGS = -fPIC -shared
   LD_FLAGS = -Wl,-rpath=../make:../../lib:$(MD)
   LIB_SUFFIX = so
endif
ifeq ($(UNAME_S),Darwin)
# Macs dont have realpath so cd to dir and get its location manually
# We check if folder exists first, to stop adipls getting confused
# when it can't find ../../lib
ifneq ($(wildcard $(MESA_DIR)/lib/.*),)
   MD := $(shell cd "$(MESA_DIR)/lib"; pwd -P)
endif
   LIB_FLAGS = -dynamiclib
   LD_FLAGS = -Wl,-rpath,../make,-rpath,../../lib,-rpath,$(MD)
   LIB_SUFFIX = dylib
endif
   LIB_TOOL = $(FC) $(LIB_FLAGS) $(FCopenmp) $(LD_FLAGS) -o

else
   # Static library options
   LIB_TOOL = $(LIB_TOOL_STATIC)
   LIB_SUFFIX = $(LIB_SUFFIX_STATIC)
   LIB_FLAGS =
   LIBS =
endif

# some definitions used in the module makefiles
MODULE_DIR = ..
MOD_PUBLIC_DIR = $(MODULE_DIR)/public
MOD_PRIVATE_DIR = $(MODULE_DIR)/private
MODULE_INCLUDES = -I$(MOD_PUBLIC_DIR) -I$(MOD_PRIVATE_DIR)
OTHER_INCLUDES = -I$(MESA_DIR)/include $(INCLUDE_HDF5)
INCLUDES = $(MODULE_INCLUDES) $(OTHER_INCLUDES) 

COMPILE_BASIC_FLAGS = $(FCbasic) $(FCopenmp) $(FCstatic) $(FCstandard) $(LIB_FLAGS) $(INCLUDES)
COMPILE_BASIC = $(FC) $(COMPILE_BASIC_FLAGS)

COMPILE_TO_TEST   = $(COMPILE_BASIC) $(FCwarn) $(FCimpno) $(FCchecks) $(FCopt) $(FCdebug) -c
COMPILE_TO_DEPLOY = $(COMPILE_BASIC) $(FCwarn) $(FCimpno) $(FCopt) -c

COMPILE_NO_OPENMP_NO_OPT = \
   $(FC) $(FCbasic) $(INCLUDES) $(FCwarn) $(FCimpno) $(FCchecks) $(FCdebug) -c -O
COMPILE_ASAP = \
   $(FC) $(FCbasic) $(INCLUDES) $(FCwarn) $(FCimpno) $(FCdebug) -c -O

COMPILE_FAST = $(COMPILE_BASIC) -c
COMPILE_NO_CHECKS = $(COMPILE_BASIC) $(FCopt) -c
COMPILE_NO_OPT    = $(COMPILE_BASIC) $(FCwarn) $(FCimpno) $(FCchecks) $(FCdebug) -c -O
COMPILE_DEVEL     = $(COMPILE_NO_OPT)


# some definitions used in the test makefiles and client makefiles

WORK_COMPILE = \
   $(FC) $(FCbasic) $(FCopenmp) $(FCchecks) $(FCdebug) $(FCfree) \
   -I$(MESA_INCLUDE_DIR) -I$(WORK_SRC_DIR) -c

ifeq ($(USE_PGPLOT),YES)
	WORK_COMPILE += -DUSE_PGPLOT
endif

TEST_DIR = ..
TEST_SRC_DIR = $(TEST_DIR)/src
PACKAGE_DIR = ../..
LOCAL_LIB_DIR = $(PACKAGE_DIR)/make
MESA_LIB_DIR = $(MESA_DIR)/lib
MESA_INCLUDE_DIR = $(MESA_DIR)/include
TEST_INCLUDES = -I$(LOCAL_LIB_DIR) -I$(PACKAGE_DIR)/public -I$(MESA_INCLUDE_DIR)
TEST_COMPILE_FLAGS = $(FCbasic) $(FCopenmp) $(TEST_INCLUDES) $(FCchecks) $(FCdebug) $(LIB_FLAGS) -c
TEST_COMPILE = $(FC) $(TEST_COMPILE_FLAGS) $(LD_FLAGS)

# Library lists / linking commands

LIBS_MATRIX = mtx const math utils
LOAD_MATRIX_INT = $(addprefix -l,$(LIBS_MATRIX))
LOAD_MATRIX_EXT = $(LOAD_CRMATH) $(LOAD_LAPACK95) $(LOAD_LAPACK) $(LOAD_BLAS)
LOAD_MATRIX = $(LOAD_MATRIX_INT) $(LOAD_MATRIX_EXT)

LIBS_MESA_NUMERICS = interp_2d interp_1d num auto_diff $(LIBS_MATRIX)
LOAD_MESA_NUMERICS_INT = $(addprefix -l,$(LIBS_MESA_NUMERICS))
LOAD_MESA_NUMERICS_EXT = $(LOAD_MATRIX_EXT) $(LOAD_HDF5)
LOAD_MESA_NUMERICS = $(LOAD_MESA_NUMERICS_INT) $(LOAD_MESA_NUMERICS_EXT)

LIBS_MESA_MICRO = star_data net eos kap rates neu chem $(LIBS_MESA_NUMERICS)
LOAD_MESA_MICRO_INT = $(addprefix -l,$(LIBS_MESA_MICRO))
LOAD_MESA_MICRO_EXT = $(LOAD_MESA_NUMERICS_EXT)
LOAD_MESA_MICRO = $(LOAD_MESA_MICRO_INT) $(LOAD_MESA_MICRO_EXT)

LIBS_MESA_MACRO = ionization atm colors $(LIBS_MESA_MICRO)
LOAD_MESA_MACRO_INT = $(addprefix -l,$(LIBS_MESA_MACRO))
LOAD_MESA_MACRO_EXT = $(LOAD_MESA_MICRO_EXT)
LOAD_MESA_MACRO = $(LOAD_MESA_MACRO_INT) $(LOAD_MESA_MACRO_EXT)

LIBS_MESA_STAR_SUPPORT = gyre $(LIBS_MESA_MACRO)
LOAD_MESA_STAR_SUPPORT_INT = $(addprefix -l,$(LIBS_MESA_STAR_SUPPORT))
LOAD_MESA_STAR_SUPPORT_EXT = $(LOAD_MESA_MACRO_EXT) $(LD_FLAGS)
LOAD_MESA_STAR_SUPPORT = $(LOAD_MESA_STAR_SUPPORT_INT) $(LOAD_MESA_STAR_SUPPORT_EXT)

LIBS_STAR_MODS = star $(LIBS_MESA_STAR_SUPPORT)
LOAD_STAR_MODS_INT = $(addprefix -l,$(LIBS_STAR_MODS))
LOAD_STAR_MODS_EXT = $(LOAD_MESA_STAR_SUPPORT_EXT)
LOAD_STAR_MODS = $(LOAD_STAR_MODS_INT) $(LOAD_STAR_MODS_EXT)

LIBS_MESA_STAR = $(LIBS_STAR_MODS)
LOAD_MESA_STAR_INT = -L$(MESA_LIB_DIR) $(addprefix -l,$(LIBS_MESA_STAR))
ifeq ($(USE_PGSTAR),YES)
   LOAD_MESA_STAR_EXT = $(LOAD_STAR_MODS_EXT) $(LOAD_PGPLOT)
else
   LOAD_MESA_STAR_EXT = $(LOAD_STAR_MODS_EXT) 
endif
LOAD_MESA_STAR = $(LOAD_MESA_STAR_INT) $(LOAD_MESA_STAR_EXT)

LIBS_MESA_BINARY = binary $(LIBS_MESA_STAR)
LOAD_MESA_BINARY_INT = -L$(MESA_LIB_DIR) $(addprefix -l,$(LIBS_MESA_BINARY))
LOAD_MESA_BINARY_EXT = $(LOAD_MESA_STAR_EXT)
LOAD_MESA_BINARY = $(LOAD_MESA_BINARY_INT) $(LOAD_MESA_BINARY_EXT)

# LOADER creates executables
LOADER = $(FC) $(LDFLAGS)

STAR_WORK_OBJS = \
   run_star_extras.o run_star.o 

BINARY_WORK_OBJS = \
   $(STAR_WORK_OBJS) run_binary_extras.o run_binary.o
   
#Test if we are on windows
BUILD_ON_WINDOWS=NO
ifeq ($(OS),Windows_NT)
   BUILD_ON_WINDOWS=YES
endif

# Declare phony targets
.PHONY: all clean install install_lib install_mod

# Path to cp_if_newer script
CP_IF_NEWER = $(MESA_DIR)/utils/cp_if_newer

# makedepf90 invocation (depends on whether we have the SDK2-patched version that
# supports the -X flag)
ifneq ($(shell makedepf90 -V | grep sdk2),)
    MAKEDEPF90_IGNORE_MODS = intrinsic omp_lib iso_c_binding iso_fortran_env ieee_arithmetic crmath hdf5
    MAKEDEPF90 := $(MESA_DIR)/utils/makedepf90-2.8.8/makedepf90 -m %m.mod -X $(addprefix -u,$(MAKEDEPF90_IGNORE_MODS))
else
    MAKEDEPF90 := $(MESA_DIR)/utils/makedepf90-2.8.8/makedepf90 -m %m.mod
endif
    
