PS_PATH = ../
INC = -I$(PS_PATH)
CXX = g++
#CXX = mpicxx
CXXFLAGS = -std=c++17 -O3 -Wall
#CXXFLAGS += -ffast-math
#CXXFLAGS += -funroll-loops
#CXXFLAGS += -DPARTICLE_SIMULATOR_THREAD_PARALLEL -fopenmp
#CXXFLAGS += -DPARTICLE_SIMULATOR_MPI_PARALLEL
#CXXFLAGS += -DPARTICLE_SIMULATOR_USE_64BIT_KEY

# Select at most one GPU mode. If neither is yes, build the CPU version.
use_gpu_walk = yes
#use_multiwalk = yes

ifeq ($(use_gpu_walk),yes)
ifeq ($(use_multiwalk),yes)
$(error use_gpu_walk and use_multiwalk cannot both be yes)
endif
endif

CUDA_HOME = /usr/local/cuda
CUDA_ARCH = 86
NVCC = time $(CUDA_HOME)/bin/nvcc
CUDA_LIBS = -L$(CUDA_HOME)/lib64 -lcudart -lgomp
CUDA_ARCH_FLAGS = -gencode arch=compute_$(CUDA_ARCH),code=sm_$(CUDA_ARCH)
CUDA_GPU_WALK_FLAGS = -std=c++17 -O3 -x cu
CUDA_GPU_WALK_FLAGS += -DUSE_GPU_WALK
CUDA_GPU_WALK_FLAGS += -DPARTICLE_SIMULATOR_ENABLE_CUDA
CUDA_GPU_WALK_FLAGS += --extended-lambda
CUDA_GPU_WALK_FLAGS += -Xcompiler="-std=c++17 -O3"
#CUDA_GPU_WALK_FLAGS += -DOPTIMIZED_VERSION
CUDA_GPU_WALK_FLAGS += $(CUDA_ARCH_FLAGS)
CUDA_MULTIWALK_FLAGS = -std=c++17 -O3 -DPARTICLE_SIMULATOR_ENABLE_CUDA --extended-lambda $(CUDA_ARCH_FLAGS)
ifeq ($(use_gpu_walk),yes)
TARGET = nbody_gpu_walk.out
else ifeq ($(use_multiwalk),yes)
TARGET = nbody_multiwalk.out
else
TARGET = nbody_cpu.out
endif

#use_phantom_grape_x86 = yes
#use_pikg_x86 = yes

# fdps-autotest-set-vars (DO NOT CHANGE THIS LINE)

ifeq ($(use_phantom_grape_x86),yes)
PG_ROOT = $(PS_PATH)/phantom_grape_x86/G5/newton/libpg5
INC += -I$(PG_ROOT)
CXXFLAGS += -DENABLE_PHANTOM_GRAPE_X86
CLIBS += -L$(PG_ROOT) -lpg5
PG_BUILD = cd $(PG_ROOT) && $(MAKE) distclean libpg5.a
PG_CLEAN = cd $(PG_ROOT) && $(MAKE) distclean
else
PG_BUILD =
PG_CLEAN =
endif

PIKG_ROOT = ../../../pikg
PIKG = $(PIKG_ROOT)/bin/pikg
ifeq ($(use_pikg_x86),yes)
INC += -I$(PIKG_ROOT)/inc
CXXFLAGS += -DUSE_PIKG_KERNEL -DPIKG_USE_FDPS_VECTOR
PIKG_FILES = kernel_pikg.hpp
CONVERSION_TYPE = reference
#CONVERSION_TYPE = AVX2
#CXXFLAGS += -mavx2 -mfma -ffast-math
#CONVERSION_TYPE = AVX-512
#CXXFLAGS += -mavx512f -mavx512dq -ffast-math
PIKG_FLAGS = --conversion-type $(CONVERSION_TYPE)
endif

all: $(TARGET)

nbody_cpu.out: nbody_cpu.o $(PIKG_FILES)
	$(PG_BUILD)
	$(CXX) $(CXXFLAGS) -o $@ nbody_cpu.o $(CLIBS)

nbody_cpu.o: nbody.cpp user-defined.hpp
	$(CXX) $(INC) $(CXXFLAGS) -c -o $@ $<

nbody_multiwalk.out: nbody.cpp user-defined.hpp force_multiwalk.hpp cuda_pointer.h
	$(NVCC) $(INC) $(CUDA_MULTIWALK_FLAGS) -x cu -DUSE_MULTIWALK -o $@ $< $(CUDA_LIBS)

nbody_gpu_walk.out: nbody.cpp user-defined.hpp force_cuda_walk.hpp Makefile
	$(NVCC) -ccbin $(CXX) $(INC) $(CUDA_GPU_WALK_FLAGS) -o $@ $<

kernel_pikg.hpp: kernel_epep.pikg
	$(PIKG) $(PIKG_FLAGS) --epi-name Epi --epj-name Epj --force-name Force --kernel-name CalcGravityEpEp -i kernel_epep.pikg -o $@

clean:
	rm -f *.o *.out kernel_pikg.hpp *~

distclean: clean
	$(PG_CLEAN)
	rm -rf result

test:
	# This command is only for FDPS developers.
	./test.py

# fdps-autotest-run (DO NOT CHANGE THIS LINE)
