Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
Merge pull request #20 from carlislewishard/debug
Browse files Browse the repository at this point in the history
Debug
  • Loading branch information
carlislewishard authored and GitHub committed Aug 3, 2023
2 parents 4122887 + 822108c commit fc27eac
Show file tree
Hide file tree
Showing 35 changed files with 1,155 additions and 627 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
!*/
# whitelist only the files that ever need to be tracked
!*.f90
!*.sh
swiftest_driver.sh
!CMakeLists.txt
!*.cmake
!COPYING.txt
Expand All @@ -23,6 +23,8 @@ dump*
!examples/**
*ipynb_checkpoints
**/.DS_Store
!python/swiftest/tests/test_suite.py
!version.txt

#Documentation
!docs/*
Expand Down
81 changes: 54 additions & 27 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
# Define the project and the depencies that it has
##################################################

CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5...3.20.1)
PROJECT(Swiftest Fortran)
CMAKE_MINIMUM_REQUIRED(VERSION 3.20.1)
# Get version stored in text file
FILE(READ "version.txt" VERSION)
PROJECT(Swiftest VERSION ${VERSION} LANGUAGES Fortran)

# Set the Swiftest version
SET(VERSION 1.0.0)
INCLUDE(CTest)

# Add our local modlues to the module path
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/")
Expand All @@ -27,29 +28,32 @@ IF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90)
MESSAGE(FATAL_ERROR "Fortran compiler does not support F90")
ENDIF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90)


IF (CMAKE_Fortran_COMPILER_ID MATCHES "^Intel")
SET(COMPILER_OPTIONS "Intel" CACHE STRING "Compiler identified as Intel")
ELSEIF (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
SET(COMPILER_OPTIONS "GNU" CACHE STRING "Compiler identified as gfortran")
ELSE ()
MESSAGE(FATAL_ERROR "Compiler not recognized!")
ENDIF ()

# Set some options the user may choose
OPTION(USE_COARRAY "Use Coarray Fortran for parallelization of test particles" OFF)
OPTION(USE_OPENMP "Use OpenMP for parallelization" ON)
OPTION(USE_SIMD "Use SIMD vectorization" ON)
OPTION(CONTAINERIZE "Compiling for use in a Docker/Singularity container" OFF)
OPTION(BUILD_SHARED_LIBS "Build using shared libraries" ON)

INCLUDE(${CMAKE_MODULE_PATH}/SetParallelizationLibrary.cmake)
INCLUDE(${CMAKE_MODULE_PATH}/SetUpNetCDF.cmake)
INCLUDE(${CMAKE_MODULE_PATH}/SetMKL.cmake)
IF (COMPILER_OPTIONS STREQUAL "Intel")
INCLUDE(${CMAKE_MODULE_PATH}/SetMKL.cmake)
ENDIF ()

# This INCLUDE statement executes code that sets the compile flags for DEBUG,
# RELEASE, PROFILING, and TESTING.
INCLUDE(${CMAKE_MODULE_PATH}/SetFortranFlags.cmake)

INCLUDE_DIRECTORIES($ENV{NETCDF_FORTRAN_HOME}/include;$ENV{NETCDF_HOME}/include)

# There is an error in CMAKE with this flag for pgf90. Unset it
GET_FILENAME_COMPONENT(FCNAME ${CMAKE_Fortran_COMPILER} NAME)
IF(FCNAME STREQUAL "pgf90")
UNSET(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS)
ENDIF(FCNAME STREQUAL "pgf90")

############################################################
# Define the actual files and folders that make up the build
############################################################
Expand All @@ -62,28 +66,51 @@ SET(SRC ${CMAKE_SOURCE_DIR}/src)
SET(LIB ${CMAKE_SOURCE_DIR}/lib)
SET(BIN ${CMAKE_SOURCE_DIR}/bin)
SET(MOD ${CMAKE_SOURCE_DIR}/include)
SET(TEST ${CMAKE_SOURCE_DIR}/test)
SET(PY ${CMAKE_SOURCE_DIR}/python/swiftest)

FUNCTION(REPLACE_VERSION IN_FILE LANGUAGE)
# Make list of strings from file
FILE(STRINGS ${IN_FILE} LINES)

# Replace file with new one
FILE(WRITE ${IN_FILE} "")

# Look for the word "VERSION" and replace the line with the updated one
FOREACH(LINE IN LISTS LINES)
IF (LANGUAGE STREQUAL "Fortran") # This is the version found in the swiftest driver program
STRING(FIND "${LINE}" " VERSION =" LINE_HAS_VER)
IF (LINE_HAS_VER GREATER_EQUAL 0) # This is the version line
FILE(APPEND ${IN_FILE} " character(*), parameter :: VERSION = \"${CMAKE_PROJECT_VERSION}\" !! Swiftest version\n")
ELSE ()
FILE(APPEND ${IN_FILE} "${LINE}\n") # No match. Put this line back like we found it
ENDIF ()
ELSEIF (LANGUAGE STREQUAL "Python") # This is the version found in the Python package
STRING(FIND "${LINE}" "version=" LINE_HAS_VER)
IF (LINE_HAS_VER GREATER_EQUAL 0) # This is the version line
FILE(APPEND ${IN_FILE} " version='${CMAKE_PROJECT_VERSION}',\n")
ELSE ()
FILE(APPEND ${IN_FILE} "${LINE}\n") # No match. Put this line back like we found it
ENDIF ()
ENDIF ()
ENDFOREACH ()
ENDFUNCTION ()

REPLACE_VERSION(${SRC}/globals/globals_module.f90 "Fortran" )
REPLACE_VERSION(${PY}/setup.py "Python")


# Have the .mod files placed in the lib folder
SET(CMAKE_Fortran_MODULE_DIRECTORY ${MOD})

# The source for the SWIFTEST binary and have it placed in the bin folder
ADD_SUBDIRECTORY(${SRC} ${BIN})

# Set up test directory
ENABLE_TESTING()
ADD_SUBDIRECTORY(${TEST})

# Add a distclean target to the Makefile
ADD_CUSTOM_TARGET(distclean
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/distclean.cmake
)

# Add an automatic test
ADD_CUSTOM_TARGET(Run_Test ALL
COMMAND echo "***Running Python script examples/Basic_Simulation/initial_conditions.py***"
COMMAND python ${CMAKE_SOURCE_DIR}/examples/Basic_Simulation/initial_conditions.py
COMMAND echo "***Saving data to directory examples/Basic_Simulation/simdata***"
COMMAND echo "***Running Python script examples/Basic_Simulation/output_reader.py***"
COMMAND python ${CMAKE_SOURCE_DIR}/examples/Basic_Simulation/output_reader.py
COMMAND echo "***Plotting results as examples/Basic_Simulation/output.eps***"
COMMAND echo "***Calculating errors with Python script examples/Basic_Simulation/errors.py***"
COMMAND python ${CMAKE_SOURCE_DIR}/examples/Basic_Simulation/errors.py
COMMAND echo "***Test Complete***"
)

29 changes: 15 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,11 @@ ENV F77="${FC}"
# https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2023-1/x-qx.html
ARG MACHINE_CODE_VALUE="sse2"

# Build type options are DEBUG, RELEASE, PROFILE, or TESTING.
ARG BUILD_TYPE="RELEASE"

# Additional CMAKE options:
ARG EXTRA_CMAKE_OPTIONS=""

# Swiftest
ENV NETCDF_HOME=${INSTALL_DIR}
ENV NETCDF_FORTRAN_HOME=${NETCDF_HOME}
Expand All @@ -109,10 +111,11 @@ COPY ./src/ /swiftest/src/
COPY ./CMakeLists.txt /swiftest/
RUN cd swiftest && \
cmake -S . -B build -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
-DMACHINE_CODE_VALUE=${MACHINE_CODE} \
-DMACHINE_CODE_VALUE=${MACHINE_CODE_VALUE} \
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DUSE_COARRAY=OFF \
-DBUILD_SHARED_LIBS=OFF && \
-DBUILD_SHARED_LIBS=OFF \
${EXTRA_CMAKE_OPTIONS} && \
cmake --build build && \
cmake --install build

Expand All @@ -133,20 +136,18 @@ ENV SHELL="/bin/bash"
ENV PATH="/opt/conda/bin:${PATH}"
ENV LD_LIBRARY_PATH="/usr/local/lib"

COPY --from=build_driver /usr/local/bin/swiftest_driver /opt/conda/bin/swiftest_driver
COPY ./python/. /opt/conda/pkgs/
COPY environment.yml .

RUN conda update --all -y && \
conda install conda-libmamba-solver -y && \
conda config --set solver libmamba

COPY environment.yml .
RUN conda env create -f environment.yml && \
conda config --set solver libmamba && \
conda install conda-build -y && \
conda env create -f environment.yml && \
cd /opt/conda/pkgs/swiftest && conda develop . --name swiftest-env && \
conda init bash && \
echo "conda activate swiftest-env" >> ~/.bashrc

COPY ./python/. /opt/conda/pkgs/
COPY --from=build_driver /usr/local/bin/swiftest_driver /opt/conda/bin/swiftest_driver

# Start new shell to activate the environment and install Swiftest
RUN cd /opt/conda/pkgs/swiftest && conda develop . && \
echo "conda activate swiftest-env" >> ~/.bashrc && \
conda clean --all -y && \
mkdir -p /.astropy && \
chmod -R 777 /.astropy && \
Expand Down
73 changes: 46 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,55 +63,74 @@ $ git pull

You now have a Swiftest repository on your personal machine that you may compile, edit, and run as you see fit.

**Compiling Swiftest**
**Compiling the Swiftest driver program**

Swiftest is written in modern Fortran and must be compiled before it can be run. After compilation, an executable, called the Swiftest driver, will have been created in the ```/swiftest/bin/``` directory.

Swiftest is compiled through [CMake](https://cmake.org/). Compiling with CMake has a number of benefits that provide a streamlined experience for the Swiftest user and developer. At compilation, CMake will automatically select the set of flags that are compatible with the local compiler. CMake also allows a Swiftest developer to re-compile only the files that have been edited, instead of requiring the developer to re-compile the entire Swiftest program. Please visit the CMake website for more information on how to install CMake.

Once CMake is installed, navigate to the topmost directory in your Swiftest repository. It is best practice to create a ```build``` directory in your topmost directory from which you will compile Swiftest. This way, temporary CMake files will not clutter up the ```swiftest/src/``` sub-directories. To create a new directory and then navigate into that directory, type the following:
***Compiling `swiftest_driver` using Docker***

By far the simplest, most reliable way of compiling the driver program is via a Docker container. The Swiftest project contains a Dockerfile that may be used to generate an executable without needing to provide any external dependencies, other than the Docker engine itself (see [here](https://docs.docker.com/get-docker/) for instructions on obtaining Docker). Once Docker is installed and the Docker engine is running, execute:
```
$ mkdir build
$ cd build
$ docker build --target=export_driver \
--output=bin \
--build-arg MACHINE_CODE_VALUE="Host" \
[ --build-arg BUILD_TYPE="*RELEASE*|DEBUG|TESTING|PROFILE" ] \
[ --build-arg EXTRA_CMAKE_OPTIONS="-D<Additional option you want to pass to CMake>" ]
```

The Docker build will download and compile all of the library dependencies (HDF5, NetCDF-C, and NetCDF-Fortran) as static libraries and the Swiftest driver using Intel compilers. Once completed, the Swiftest executable, called ```swiftest_driver```, should now be created in the ```bin/``` directory.

> Note: The Dockerfile is designed to build an executable that is compatible with a broad range of CPU architectures by specifying the SSE2 instruction as a target for SIMD instructions using the `-x` compiler option. When compiling on the same CPU archictecture you plan to execute the driver program, for the highest possible SIMD performance, use `--build-arg MACHINE_CODE_VALUE="Host" to override the default `MACHINE_CODE_VALUE="SSE2"`. For additional options see [here](https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2023-1/x-qx.html).
The optional Docker argument `EXTRA_CMAKE_OPTIONS` is provided to pass any additional CMake arguments (see below).


***Compiling `swiftest_driver` using CMake***

The Swiftest driver program is written in modern Fortran and must be compiled before it can be run. After compilation, an executable, called the `swiftest_driver``, will have been created in the ```bin/``` directory.

Swiftest is compiled through [CMake](https://cmake.org/). Compiling with CMake has a number of benefits that provide a streamlined experience for the Swiftest user and developer. At compilation, CMake will automatically select the set of flags that are compatible with the local compiler. CMake also allows a Swiftest developer to re-compile only the files that have been edited, instead of requiring the developer to re-compile the entire Swiftest program. Please visit the CMake website for more information on how to install CMake.

As mentioned in the **System Requirements** section, Swiftest requires the NetCDF and NetCDF Fortran libraries to be installed prior to compilation. If the libraries are installed in the standard library location on your machine, CMake should be able to find the libraries without specifying the path. However, if CMake struggles to find the NetCDF libraries, there are two ways to set the path to these libraries.

1. Create an environment variable called ```NETCDF_FORTRAN_HOME``` that contains the path to the location where the libraries are installed
2. Set the path at the time of compilation using ```-DCMAKE_PREFIX_PATH=/path/to/netcdf/```
2. Set the path at the build step using ```-CMAKE_PREFIX_PATH=/path/to/netcdf/```

CMake allows the user to specify a set of compiler flags to use during compilation. We define five sets of compiler flags: release, testing, profile, math, and debug. To view and/or edit the flags included in each set, see ```swiftest/cmake/Modules/SetFortranFlags.cmake```.

As a general rule, the release flags are fully optimized and best used when running Swiftest with the goal of generating results. This is the default set of flags. When making changes to the Swiftest source code, it is best to compile Swiftest using the debug set of flags. You may also define your own set of compiler flags.

To build Swiftest with the release flags (default) using the Intel fortran compiler (ifort), type the following:
Navigate to the topmost directory in your Swiftest repository. It is best practice to create a ```build``` directory in your topmost directory from which you will compile Swiftest. This way, temporary CMake files will not clutter up the ```swiftest/src/``` sub-directories. The commands to build the source code into a ```build``` directory and compile Swiftest are:

```
$ cmake ..
$ cmake -B build -S .
$ cmake --build build
```
To build with the debug flags, type:
The [CMake Fortran template](https://github.com/SethMMorton/cmake_fortran_template) comes with a script that can be used to clean out any build artifacts and start from scratch:

```
$ cmake .. -DCMAKE_BUILD_TYPE=DEBUG
$ cmake -P distclean.cmake
```
To build with another set of flags, simply replace ```DEBUG``` in the above line with the name of the flags you wish to use.

Add ```-CMAKE_PREFIX_PATH=/path/to/netcdf/``` to these commands as needed.
The Swiftest CMake configuration comes with several customization options:

If using the GCC fortran compiler (gfortran), add the following flags:
```
-DCMAKE_Fortran_FLAGS="-I/usr/lib64/gfortran/modules/ -ffree-line-length-512"
```
You can manually specify the compiler you wish to use with the following flag:
```
c-DCMAKE_Fortran_COMPILER=$(which ifort)
```
| Option | CMake command |
| --------------------------------|------------------------------------------------------------|
| Build type | \-DCMAKE_BUILD_TYPE=[**RELEASE**\|DEBUG\|TESTING\|PROFILE] |
| Enable/Disable OpenMP support | \-DUSE_OPENMP=[**ON**\|OFF] |
| Enable/Disable SIMD directives | \-DUSE_SIMD=[**ON**\|OFF] |
| Enable/Disable Coarray support (experimental) | \-DUSE_COARRAY=[ON\|**OFF**] |
| Set Fortran compiler path | \-DCMAKE_Fortran_COMPILER=/path/to/fortran/compiler |
| Set path to make program | \-DCMAKE_MAKE_PROGRAM=/path/to/make |
| Enable/Disable shared libraries (Intel only) | \-DBUILD_SHARED_LIBS=[**ON\|OFF] |
| Add additional include path | \-DCMAKE_Fortran_FLAGS="-I/path/to/libries |

After building Swiftest, make the executable using:

To see a list of all possible options available to CMake:
```
$ make
$ cmake -B build -S . -LA
```

The Swiftest executable, called ```swiftest_driver```, should now be created in the ```/swiftest/bin/``` directory.
The Swiftest executable, called ```swiftest_driver```, should now be created in the ```bin/``` directory.


**Download the `swiftest_driver` as a Docker or Singularity container.**

Expand Down Expand Up @@ -493,7 +512,7 @@ This example walks through how to set up a standard solar system simulation. It
- Semi-Interacting Massive Bodies - Gravitationally affect and are affected by fully-interacting massive bodies, do not gravitationally affect and are not affected by other semi-interacting massive bodies.
- Test Particles - Gravitationally affected by fully-interacting massive bodies only.

To generate the initial conditions, run the Python script titled **initial_conditions.py**. This script also runs Swiftest SyMBA, generating output. To process the output file, run the script titled **output_reader.py**.
To generate the initial conditions, run the Python script titled **basic_simulation.py**. This script also runs Swiftest SyMBA, generating output. To process the output file, run the script titled **output_reader.py**.

**Chambers2013**

Expand Down
51 changes: 32 additions & 19 deletions cmake/Modules/FindCoarray_Fortran.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,40 @@ INCLUDE (${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake)

STRING(TOUPPER "${CMAKE_BUILD_TYPE}" BT)
IF(BT STREQUAL "DEBUG")
SET (Coarray_Fortran_FLAG_CANDIDATES
#Intel
"-coarray=single"
#Intel windows
"/Qcoarray:single"
#Gnu
"-fcoarray=single"
#Empty, if compiler automatically accepts coarray
" "
IF (COMPILER_OPTIONS STREQUAL "Intel")
SET (Coarray_Fortran_FLAG_CANDIDATES
#Intel
"-coarray=single"
#Intel windows
"/Qcoarray:single"
#Empty, if compiler automatically accepts coarray
" "
)
ELSEIF (COMPILER_OPTIONS STREQUAL "GNU")
SET (Coarray_Fortran_FLAG_CANDIDATES
#Gnu
"-fcoarray=single"
#Empty, if compiler automatically accepts coarray
" "
)
ENDIF()
ELSE()
SET (Coarray_Fortran_FLAG_CANDIDATES
#Intel
"-coarray=distributed"
#Intel windows
"/Qcoarray:distributed"
#Gnu
"-fcoarray=lib -lcaf_mpi"
#Empty, if compiler automatically accepts coarray
" "
)
IF (COMPILER_OPTIONS STREQUAL "Intel")
SET (Coarray_Fortran_FLAG_CANDIDATES
#Intel
"-coarray=distributed"
#Intel windows
"/Qcoarray:distributed"
#Empty, if compiler automatically accepts coarray
" "
)
ELSEIF (COMPILER_OPTIONS STREQUAL "GNU")
SET (Coarray_Fortran_FLAG_CANDIDATES
#Gnu
"-fcoarray=lib -lcaf_mpi"
#Empty, if compiler automatically accepts coarray
" "
)
ENDIF()


Expand Down
Loading

0 comments on commit fc27eac

Please sign in to comment.