Skip to content
Snippets Groups Projects
Commit c4d8df51 authored by Philipp Rüssmann's avatar Philipp Rüssmann
Browse files

Cherry-pick NPY-for-Fortran

parent bb468edd
No related branches found
No related tags found
No related merge requests found
...@@ -110,6 +110,8 @@ add_library(lib_common STATIC ...@@ -110,6 +110,8 @@ add_library(lib_common STATIC
source/common/mathtools.f90 source/common/mathtools.f90
source/common/bfield.f90 source/common/bfield.f90
source/common/torque.f90 source/common/torque.f90
source/external/NPY-for-Fortran/src/npy.F90
source/external/NPY-for-Fortran/src/endian_swap.f90
) )
# disable cmake auto add of 'lib' prefix to .so file # disable cmake auto add of 'lib' prefix to .so file
SET_TARGET_PROPERTIES(lib_common PROPERTIES PREFIX "") SET_TARGET_PROPERTIES(lib_common PROPERTIES PREFIX "")
......
This diff is collapsed.
CMakeCache.txt
CMakeFiles/*
Makefile
cmake_install.cmake
*.x
*.mod
cmake_minimum_required(VERSION 2.8)
project(STB)
file(GLOB_RECURSE sources src/*.f90
src/*.F90
src/*.h )
add_executable(npy.x ${sources})
enable_language(Fortran)
set(CMAKE_Fortran_COMPILER ifort)
set(CMAKE_Fortran_COMPILER_ID "Intel")
if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
set(dialect "-ffree-form -cpp -std=gnu -fimplicit-none")
#set(bounds "-fbounds-check")
endif()
if(CMAKE_Fortran_COMPILER_ID MATCHES "Intel")
#set(bounds "-check bounds")
endif()
if(CMAKE_Fortran_COMPILER_ID MATCHES "PGI")
set(dialect "-Mfreeform -Mdclchk -Mstandard -Mallocatable=03")
#set(bounds "-C")
endif()
set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} ${bounds}")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${dialect}")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
MESSAGE( STATUS "cmake_module_path: " ${CMAKE_MODULE_PATH})
#
# Compile.
#
MIT License
Copyright (c) 2017 Matthias Redies
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# NPY for Fortran
This Fortran module allows to save numerical Fortran arrays in Numpy's .npy or .npz format. Currently supported are:
```fortran
1. integer(1), integer(2), integer(4), integer(8)
2. real(4), real(8)
3. complex(4), complex(8)
```
### *.npy files
Saving an array into a .npy-file is simply done by calling:
```fortran
call save_npy("filename.npy", array)
```
### *.npz files
In order to save .npz-files the commandline tool 'zip' has to be installed. By calling
```fortran
call add_npz("example.npz", "temperature", data_array)
```
one creates an .npz-file containing data_array, with the name "temperature". If example.npz already exists the field "temperature" is added to it. If the field temperature already exsits in example.npz it will be overwritten.
Reading .npy and .npz files isn't currently supported. (Maybe someone can give me ideas on dynamic typing in Fortran...)
### Compiling using ifort
The code uses the somewhat out-dated
```fortran
succ = system(...)
```
command for which ifort needs the the IFPORT library:
```fortran
#ifdef INTEL_COMPILER_USED
USE IFPORT
#endif
```
Therefore, Intel users need to add the flag:
```
-DINTEL_COMPILER_USED
```
### Compiling using gfortran
Since the function 'system' is not standard Fortran one cannot use flags such as
```
-std=f2008
```
but instead can (not must) use the equivalent
```
-std=gnu
```
### Control Flags
In the source file the parameter
```fortran
character(len=*), parameter :: zip_flag = "-q0"
```
can be used to control the compression. "-q0" tells the zip tool to have no output and no compression.
### Endianess
Using the flag
```fortran
logical, parameter :: use_big_endian = .False.
```
the output [endianess](https://en.wikipedia.org/wiki/Least_significant_bit) can be set. This works independent of the compiler. Little endian (.False.) is a reasonable default for most personal computers.
\ No newline at end of file
theme: jekyll-theme-minimal
\ No newline at end of file
module endian_swap
implicit none
PRIVATE
PUBLIC :: Big_Endian
PUBLIC :: Swap_Endian
INTERFACE Swap_Endian
module procedure SWAP_I1
module procedure SWAP_I2
module procedure SWAP_I4
module procedure SWAP_I8
module procedure SWAP_F4
module procedure SWAP_F8
module procedure SWAP_F16
module procedure SWAP_C4
module procedure SWAP_C8
END INTERFACE Swap_Endian
CONTAINS
FUNCTION Big_Endian()
LOGICAL :: Big_Endian
Big_Endian = ichar(transfer(1,'a')) == 0
END FUNCTION Big_Endian
function SWAP_I4(input) result(output)
implicit none
integer(4), parameter :: b_sz = 4
integer(b_sz), intent(in) :: input
integer(b_sz) :: output
integer(1) :: byte_arr(b_sz), byte_arr_tmp(b_sz)
integer(1) :: i
byte_arr_tmp = transfer(input, byte_arr_tmp)
do i = 1,b_sz
byte_arr(i) = byte_arr_tmp(1 + b_sz - i)
enddo
output = transfer(byte_arr, output)
end function SWAP_I4
function SWAP_I2(input) result(output)
implicit none
integer(4), parameter :: b_sz = 2
integer(b_sz), intent(in) :: input
integer(b_sz) :: output
integer(1) :: byte_arr(b_sz), byte_arr_tmp(b_sz)
integer(1) :: i
byte_arr_tmp = transfer(input, byte_arr_tmp)
do i = 1,b_sz
byte_arr(i) = byte_arr_tmp(1 + b_sz - i)
enddo
output = transfer(byte_arr, output)
end function SWAP_I2
function SWAP_I1(input) result(output)
implicit none
integer(4), parameter :: b_sz = 1
integer(b_sz), intent(in) :: input
integer(b_sz) :: output
integer(1) :: byte_arr(b_sz), byte_arr_tmp(b_sz)
integer(1) :: i
byte_arr_tmp = transfer(input, byte_arr_tmp)
do i = 1,b_sz
byte_arr(i) = byte_arr_tmp(1 + b_sz - i)
enddo
output = transfer(byte_arr, output)
end function SWAP_I1
function SWAP_I8(input) result(output)
implicit none
integer(4), parameter :: b_sz = 8
integer(b_sz), intent(in) :: input
integer(b_sz) :: output
integer(1) :: byte_arr(b_sz), byte_arr_tmp(b_sz)
integer(1) :: i
byte_arr_tmp = transfer(input, byte_arr_tmp)
do i = 1,b_sz
byte_arr(i) = byte_arr_tmp(1 + b_sz - i)
enddo
output = transfer(byte_arr, output)
end function SWAP_I8
function SWAP_F4(input) result(output)
implicit none
integer(4), parameter :: b_sz = 4
real(b_sz), intent(in) :: input
real(b_sz) :: output
integer(1) :: byte_arr(b_sz), byte_arr_tmp(b_sz)
integer(1) :: i
byte_arr_tmp = transfer(input, byte_arr_tmp)
do i = 1,b_sz
byte_arr(i) = byte_arr_tmp(1 + b_sz - i)
enddo
output = transfer(byte_arr, output)
end function SWAP_F4
function SWAP_F8(input) result(output)
implicit none
integer(4), parameter :: b_sz = 8
real(b_sz), intent(in) :: input
real(b_sz) :: output
integer(1) :: byte_arr(b_sz), byte_arr_tmp(b_sz)
integer(1) :: i
byte_arr_tmp = transfer(input, byte_arr_tmp)
do i = 1,b_sz
byte_arr(i) = byte_arr_tmp(1 + b_sz - i)
enddo
output = transfer(byte_arr, output)
end function SWAP_F8
function SWAP_F16(input) result(output)
implicit none
integer(4), parameter :: b_sz = 16
real(b_sz), intent(in) :: input
real(b_sz) :: output
integer(1) :: byte_arr(b_sz), byte_arr_tmp(b_sz)
integer(1) :: i
byte_arr_tmp = transfer(input, byte_arr_tmp)
do i = 1,b_sz
byte_arr(i) = byte_arr_tmp(1 + b_sz - i)
enddo
output = transfer(byte_arr, output)
end function SWAP_F16
function SWAP_C8(input) result(output)
implicit none
integer(4), parameter :: b_sz = 8
complex(b_sz), intent(in) :: input
complex(b_sz) :: output
real(b_sz) :: re, im
re = Swap_Endian(real(input))
im = Swap_Endian(aimag(input))
output = cmplx(re, im)
end function swap_c8
function SWAP_C4(input) result(output)
implicit none
integer(4), parameter :: b_sz = 4
complex(b_sz), intent(in) :: input
complex(b_sz) :: output
real(b_sz) :: re, im
re = Swap_Endian(real(input))
im = Swap_Endian(aimag(input))
output = cmplx(re, im)
end function swap_c4
END module endian_swap
program main
use m_npy
use endian_swap
complex(8) :: a(10,20), b(10), c(2,3,4)
integer(4) :: i, j, k
real(4) :: test1
real(8) :: test2
do i = 1,size(a,1)
do j = 1,size(a,2)
a(i,j) = i * j
enddo
enddo
do i = 1,size(b,1)
b(i) = 2 * i
enddo
do i = 1,size(c,1)
do j = 1,size(c,2)
do k =1,size(c,3)
c(i,j,k) = cmplx(1, 2)
enddo
enddo
enddo
c(1,1,1) = cmplx(3,4)
c(2,3,4) = cmplx(0,1)
c(2,2,2) = cmplx(1,0)
call save_npy("c.npy", c)
end program main
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment