# Enable OpenMP flags
OMP_FLAGS = -fopenmp -DUSE_OPENMP
#OMP_FLAGS_ICPX = -qopenmp -DUSE_OPENMP
OMP_FLAGS_ICPX = -qopenmp -DUSE_OPENMP -malign-double

# Enable kinetic and potential energy calculations
#ENERGY_CHECK = -DUSE_ENERGYCHECK

# Enable additional compiler optimizations
OPTS_FLAGS = -DCOMPUTE_FORCES_OPTIMS

# Enable align directives for vectors inside the "Particle" struct
ALIGN_FLAGS = -DALIGN_CELLS

# Compiler and flags
INC_DIR = include
CXX = g++
CXXFLAGS = -std=c++17 $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS)  -Wall -Werror -Wextra -Ofast -funroll-loops -g -I$(INC_DIR) -mcpu=native $(OMP_FLAGS)
DEBUG_FLAGS = -std=c++17 $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -g -DDEBUG I$(INC_DIR) $(OMP_FLAGS)

# Target executable name
TARGET = md_cell
DEBUG_TARGET = md_cell_debug

# CHANGE - Binaries compiled into /bin
BINDIR = bin

# Source files
SRC = main.cpp simulation.cpp particle.cpp

# Object files
OBJ = $(SRC:.cpp=.o)
DEBUG_OBJ = $(SRC:.cpp=.debug.o)

# Default target
all: $(TARGET)
	@echo "╔════════════════════════════════════════════════════╗";
	@echo "║░█▄█░█▀▄░░░█▀▀░█▀▀░█░░░█░░░░░█░█░█▀▀░█▀▄░█▀█░█▀▀░█░░║";
	@echo "║░█░█░█░█░░░█░░░█▀▀░█░░░█░░░░░█▀▄░█▀▀░█▀▄░█░█░█▀▀░█░░║";
	@echo "║░▀░▀░▀▀░░░░▀▀▀░▀▀▀░▀▀▀░▀▀▀░░░▀░▀░▀▀▀░▀░▀░▀░▀░▀▀▀░▀▀▀║";
	@echo "╚════════════════════════════════════════════════════╝";
	@echo "Build complete!"

# Debug build
debug: $(DEBUG_TARGET)

# Link the object files to create the executable
$(TARGET): $(OBJ)
	mkdir -p $(BINDIR)
	$(CXX) $(CXXFLAGS) -o $(BINDIR)/$@ $^

# Link the debug object files to create the debug executable
$(DEBUG_TARGET): $(DEBUG_OBJ)
	mkdir -p $(BINDIR)
	$(CXX) $(DEBUG_FLAGS) -o $(BINDIR)/$@ $^

# Compile source files to object files
%.o: %.cpp
	$(CXX) $(CXXFLAGS) -c $< -o $@

# Compile source files to debug object files
%.debug.o: %.cpp
	$(CXX) $(DEBUG_FLAGS) -c $< -o $@

# Clean the build
clean:
	@rm -f $(OBJ) $(DEBUG_OBJ) *~

# Run the simulation
run: $(TARGET)
	$(BINDIR)/$(TARGET)

# Run the simulation with debug build
rundebug: $(DEBUG_TARGET)
	$(BINDIR)/$(DEBUG_TARGET)

# Phony targets
.PHONY: all debug clean run rundebug

gcc-O2:
	$(MAKE) clean all CXX=g++ CXXFLAGS="-std=c++17 $(OMP_FLAGS) $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -O2 -g -I$(INC_DIR) -march=native -mtune=native" TARGET=md-gcc-O2

gcc-O3:
	$(MAKE) clean all CXX=g++ CXXFLAGS="-std=c++17 $(OMP_FLAGS) $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -O3 -g -I$(INC_DIR) -march=native -mtune=native" TARGET=md-gcc-O3

gcc-Ofast:
	$(MAKE) clean all CXX=g++ CXXFLAGS="-std=c++17 $(OMP_FLAGS) $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -Ofast -g -I$(INC_DIR) -march=native -mtune=native" TARGET=md-gcc-Ofast

clang-O2:
	$(MAKE) clean all CXX=clang++ CXXFLAGS="-std=c++17 $(OMP_FLAGS) $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -O2 -g -I$(INC_DIR) -march=native -mtune=native" TARGET=md-clang-O2

clang-O3:
	$(MAKE) clean all CXX=clang++ CXXFLAGS="-std=c++17 $(OMP_FLAGS) $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -O3 -g -I$(INC_DIR) -march=native -mtune=native" TARGET=md-clang-O3

clang-O3-ffast-math:
	$(MAKE) clean all CXX=clang++ CXXFLAGS="-std=c++17 $(OMP_FLAGS) $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -O3 -ffast-math -g -I$(INC_DIR) -march=native -mtune=native" TARGET=md-clang-O3-ffast-math

icpx-O2:
	$(MAKE) clean all CXX=icpx CXXFLAGS="-std=c++17 $(OMP_FLAGS_ICPX) $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -O2 -g -I$(INC_DIR) -xHost -mtune=native" TARGET=md-icpx-O2

icpx-O3:
	$(MAKE) clean all CXX=icpx CXXFLAGS="-std=c++17 $(OMP_FLAGS_ICPX) $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -O3 -g -I$(INC_DIR) -xHost -mtune=native" TARGET=md-icpx-O3

icpx-Ofast:
	$(MAKE) clean all CXX=icpx CXXFLAGS="-std=c++17 $(OMP_FLAGS_ICPX) $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -Ofast -g -I$(INC_DIR) -xHost -mtune=native" TARGET=md-icpx-Ofast

acfl-O2:
	$(MAKE) clean all CXX=armclang++ CXXFLAGS="-std=c++17 $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -O2 -grecord-gcc-switches -g -I$(INC_DIR) -march=native -mcpu=native $(OMP_FLAGS)" TARGET=md-acfl-O2

acfl-O3:
	$(MAKE) clean all CXX=armclang++ CXXFLAGS="-std=c++17 $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -O3 -grecord-gcc-switches -g -I$(INC_DIR) -march=native -mcpu=native $(OMP_FLAGS)" TARGET=md-acfl-O3

acfl-Ofast:
	$(MAKE) clean all CXX=armclang++ CXXFLAGS="-std=c++17 $(ENERGY_CHECK) $(OPTS_FLAGS) $(ALIGN_FLAGS) -Wall -Werror -Wextra -Ofast -grecord-gcc-switches -g -I$(INC_DIR) -march=native -mcpu=native $(OMP_FLAGS)" TARGET=md-acfl-Ofast

.PHONY: gcc-O2 gcc-O3 gcc-Ofast clang-O2 clang-O3 clang-O3-ffast-math icpx-O2 icpx-O3 icpx-Ofast acfl-O2 acfl-O3 acfl-Ofast
