Skip to content

Latest commit

 

History

History
315 lines (205 loc) · 15.9 KB

README.md

File metadata and controls

315 lines (205 loc) · 15.9 KB

Coretran

An easy to follow library to make Fortran easier in general with wrapped interfaces, sorting routines, kD-Trees, and other algorithms to handle scientific data and concepts. The library contains core fortran routines and object-oriented classes.

Why coretran?

I used Fortran extensively during my PhD to solve very large systems of equations with application to the inversion of geophysical data for 3D subsurface physical property models. I developed algorithms that utilized random point clouds in space, structured rectilinear, triangular, and voronoi meshes, and the unstructured versions of these. Fortran has relatively little modern and freely available source code, compared to other languages, which have easy to use libraries that perform these types of operations.

I struggled as a beginner coming in to Fortran because the basic functions that handle numbers were not readily available. It was frustrating that I had to write (and then duplicate) my own error checking when allocating memory or opening a file. What also frustrated me was when I had to write the same function/subroutine multiple times for different input types like integers or real numbers.

I wonder, how many people have written their own function as basic as computing a mean of some numbers?

This was initially the driving motivation for me to develop this library. The simple fact that Fortran does not have these basic functions readily available, and that any user starting from scratch would have to write their own. I humbly hope that this library will help to alleviate this issue, by providing functions/subroutines with complexities that range from the most basic to the more advanced, but all in pure Fortran. The effect is hopefully similar to a Python user who has immediate access to amazing packages such as numpy and scipy.

The code comes with a complete set of source code documentation that is easily generated into html pages. These docs also contain working examples on how to run each function and subroutine within the library. Also included in the docs are the references to papers or online material that I used.

This library is written using modern Fortran standards with modules, sub modules, and object oriented derived types.

The code can be compiled easily across platforms using CMake.

Compiler Support

Compiler Compiler Compiler Compiler Compiler Compiler


Main features | Documentation | Compiling | An example of coretran


Main features

All functions and subroutines are interfaces, they work no matter the input type whether it real, or integer etc. where it makes sense.

Getting Ready for Compiling and Creating the Documentation

There are three aspects that we need to address

  1. Installing a Fortran compiler to create the libraries
  2. Installing the software build tool that compiles the codes in the correct order, so you don't have to!
  3. Install Python and the software to generate the source code documentation locally (optional! You could just go here)

Installing the GNU fortran compiler

To compile my library, I have been using gfortran version 6.3.0 because of the use of submodules and other 2008 standards. I you want to use Intel's fortran compiler you will need ifort version 17+

* Linux

If you work in Linux you should be well versed in installing packages on your system. At the time of writing this I am running on Ubuntu 16.04 LTS.

* Mac

On a Mac, I use Brew to manage my libraries/programs. So type "brew install gcc" and you should be golden.

* Windows

Windows is a little trickier but it is still easy! The easiest way I have found is to use MinGW. There is a good tutorial on installing mingw here. I will summarize below.

Go to MinGW - Downloads, and click on "Mingw-builds" in the table to redirect to sourceforge. This will download the installer.

When you run the installer, choose the following

  • Version: 6.3.0 (minimum) you may choose higher
  • Architecture: x86_64
  • Threads: posix
  • Exception: sjlj
  • Build revision: The highest number

You should change the Destination Folder so that the path does not contain any spaces.

Add an environment variable called "MinGW_Home" and point it to the bin directory in your chosen destination folder. e.g. "C:\programs\mingw-w64\x86_64-6.3.0-posix-sjlj-rt_v5-rev1\mingw64\bin"

I don't require MSYS to build my library so you can stop here if you like. I do however suggest making an alias to the MinGW32-make executable, this is optional, so later in these instructions simply replace "make" with "mingw32-make" if you choose not to do this.

Go to the bin directory in your installation folder, on my system it is "C:\programs\mingw-w64\x86_64-6.3.0-posix-sjlj-rt_v5-rev1\mingw64\bin" and create a file called "make.bat"

Edit the file with a text editor and add the following single line "mingw32-make %*" This allows you to use the command "make" on windows which we will need later to build to library.

Compilation

The library can be compiled with any custom approach you choose, however to make life easier, I have included instructions on how to use cmake to generate makefiles. Cmake allows you to easily build the same source code on Windows, OSX, and Linux with no changes. I always found make files cumbersome on Windows so Cmake made my life very easy. The portability of Cmake to multiple architectures was the driving reason for me choosing it, plus Cmake can handle the newer, more modern, aspects of Fortran 2003, 2008+, and handles source code dependencies very well.

Installing Cmake

The installation of cmake should be quite easy. Similar to the section above on installing gfortran.

On a Mac, I simply use brew again.

On windows, you should be able to download the installation binary from their website.

Compiling the coretran library

To compile the coretran library, navigate to the root directory and create a new folder "build".

Change directory to build and type

cmake [-D options] [-G option] ../src

There are a number of extra options you can pass through to this cmake command. Each option follows a -D flag.

  • -D
    • -DCMAKE_BUILD_TYPE=

      • DEBUG will add all debugging flags, tracebacks, and array bound checking. This is great for development.
      • RELEASE will turn of the less efficient checks, and will compile with higher levels of optimization. This is great for production runs once everything is debugged.
    • -DCMAKE_Fortran_COMPILER=

      • If cmake does not use the compiler you need, you can specify the path to the compiler you want. I had some issues on OSX with the intel compiler and gfortran both installed. Using -G "Unix Makefiles" would always detect the intel compiler. To force cmake to use gfortran, I used -DCMAKE_Fortran_COMPILER=/usr/local/Cellar/gcc/6.2.0/bin/gfortran (Remember I used brew to install gfortran, and that the version number might change!)
      • Even if you type "which gfortran" and it shows the correct one, cmake may still detect a lower version system level gcc/gfortran. If you encounter build errors such as "unclassifiable statement", cmake is probably using too old a version of gfortran. In this case, explicitly specify the gfortran to use with this option.
    • -DBUILD_SHARED_LIBS=

      • ON this is the default option and will build shared libraries.
      • OFF this will build static libraries.
    • -DCMAKE_INSTALL_PREFIX=

      • This allows you to specify an install directory after you compile the library. e.g. -DCMAKE_INSTALL_PREFIX=/path/to/dir will put all compiled modules in an include folder, and compiled libraries in a lib folder. Additionally, the lib folder will contain a folder called "cmake" that contains a cmake config file for coretran. If you append the lib/cmake folder to an environment variable called "CMAKE_LIBRARY_PATH" you will be able to use "find_package(coretran REQUIRED CONFIG)" in your own cmake project to make linking to coretran very easy.

Cmake can generate makefiles for a multitude of different compilers. The -G option allows you to specify which compiler you wish to generate a makefile for.

  • -G

    If you type

     cmake -h
    

    You will see not only the man pages for cmake, but also a list of generators e.g.

     Generators
    
     The following generators are available on this platform:
     Unix Makefiles                  = Generates standard UNIX makefiles.
     Ninja                           = Generates build.ninja files.
     Xcode                           = Generate Xcode project files.
     CodeBlocks - Ninja              = Generates CodeBlocks project files.
     CodeBlocks - Unix Makefiles     = Generates CodeBlocks project files.
     CodeLite - Ninja                = Generates CodeLite project files.
     CodeLite - Unix Makefiles       = Generates CodeLite project files.
     Sublime Text 2 - Ninja          = Generates Sublime Text 2 project files.
     Sublime Text 2 - Unix Makefiles = Generates Sublime Text 2 project files.
     Kate - Ninja                    = Generates Kate project files.
     Kate - Unix Makefiles           = Generates Kate project files.
     Eclipse CDT4 - Ninja            = Generates Eclipse CDT 4.0 project files.
     Eclipse CDT4 - Unix Makefiles   = Generates Eclipse CDT 4.0 project files.
     KDevelop3                       = Generates KDevelop 3 project files.
     KDevelop3 - Unix Makefiles      = Generates KDevelop 3 project files.
    

    On Windows, you should also see a generator for "MinGW Makefiles"

    So choose which one you want.

    On OSX and Linux I have always used "Unix Makefiles".

    On Windows, I have used "MinGW Makefiles" or "NMake Makefile" for gfortran or intel respectively.

    So the -G option might be " -G "Unix Makefiles" "

Finally, to compile the library, type

make

or on Windows,

mingw32-make

if you did not follow this step.

If you want to "install" coretran to the directory specified using the -DCMAKE_INSTALL_PREFIX option (see above), type

make install

Testing Coretran and running the scaling code

The makefile will automatically generate two programs, a "unit tester" and a scalability test. These programs will be located in the bin folder within the coretran repository.

To run the test program type (assuming you are still in the build folder)

../bin/coretranTest N 1

where N is a number > 15. N defines the size of arrays to use in the tests. Over 1e8 your might have slow tests...

To run the scalability program type

../bin/coretranScale

This will perform some timing tests on the sorting algorithms, selection, KDtree generation, etc. This lets you get a feel for how quickly coretran will perform these algorithms. These algorithms are not the best in the world by any means, but hopefully they are readable and usable!

How to use coretran in your library or program

Once the coretran library is compiled, you can easily use it in your own program.

  • Using your own make files or compile.bat scripts

    When you compile your Fortran codes to object files, simply use -I/ path/to/coretran/include. When you link your objects, use -L/path/ to/coretran/lib and -lcoretran.

  • Using cmake to build your own project

    If you use cmake, and you used "make install" to install coretran, you can append the path "install-path/lib/cmake" to an environment variable called "CMAKE_LIBRARY_PATH". You can then use "find_package(coretran REQUIRED CONFIG)" to easily find coretran, followed by "target_link_libraries(${PROJECT_NAME} coretran)"

Documentation

Any good software library should come with documentation. In this library, I have extensive source code comments that you should be able to follow. The source code comments also contain snippets of code that show how to use the functions I have written. In addition to this, the source code comments can be used to automatically generate html pages. These pages are fully searchable and very nicely organized. This is where Ford comes in.

The html documentation for the source code be created locally using the ford Fortran Documentation Tool. If you don't want to create it locally you can simply see it here.

You can install Ford like any other Python module using "pip install ford".

Installing and Setting up Python

I have so far found the Anaconda Distribution of Python to be the most friendly cross platform distribution. Go ahead and install Anaconda on your system, if you are on Windows, allow the installer to modify your environment variables (so you don't have to later). Ford uses python version 3+ so be sure to get the correct installer.

Ford can also generate a dependency graph of the fortran modules by using Graphviz, you will need to install Graphviz separately.

  • Windows Graphviz Installation

    I downloaded the .msi files from the Graphviz website, I then had to add the following path to my environment variables "C:\Program Files (x86)\Graphviz2.38\bin" so that Ford can use the executable. (Locate the folder where you installed Graphviz, if it is different to my path, add that to your environment variables instead).

  • OSX Graphviz Installation

    To manage my programs I use Homebrew. To install Graphviz, I simply used "brew install Graphviz"

Generating the docs

Once Ford and perhaps Graphviz are installed, simply navigate to the root coretran folder in a terminal/command prompt and type "ford Docs.md". This will generate html pages under the docs folder.

Go to Top

An example of coretran

Here is a small example of how this library makes Fortran easier to use (especially for a beginner), and how it can clean up your code. While this example is not extensive it should give you an idea.

Fortran code to allocate an array, create some numbers, and compute their mean.

program theMean_test
use, intrinsic :: iso_fortran_env, only: real64, int32
implicit none
real(real64), allocatable :: a(:)
real(real64) :: theMean
! Some parameters to handle everything
integer(int32) :: i, istat, N
N=1000

! Allocate a and check for errors
allocate(a(N), stat=istat)
if (istat /= 0) then
  stop "Could not allocate a"
endif

! Create numbers from 1 to N
a = [(real(i,kind=real64), i=1,N)]

! Compute the mean
theMean = sum(a)/real(N,kind=real64)

! Deallocate memory
deallocate(a, stat=istat)
if (istat /= 0) then
  stop "Could not deallocate a"
endif
end program

The same code using coretran

program theMean
use variableKind, only: r64,i32
use m_allocate, only: allocate
use m_deallocate, only: deallocate
use m_array1D, only: arange
use m_maths only: mean
implicit none
real(r64), allocatable :: a(:)
real(r64) :: theMean
integer(i32) :: N
N=1000

! Allocate a and check for errors
call allocate(a,N)

! Create numbers from 1 to N
call arange(a, 1.0_r64, 1000.0_r64)

! Compute the mean
theMean = mean(a)

! Deallocate memory
call deallocate(a)
end program