diff --git a/src/.gitignore b/src/.gitignore index 9b3b867..a22dab1 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,5 +1,6 @@ templates_front/*.c templates_front/*.h +templates_front/*.f90 templates_front/populated/ templates_hdf5/*.c @@ -16,8 +17,11 @@ libtrexio.so trexio.c trexio_text.c trexio_hdf5.c +trexio_f.f90 +trexio.mod test -test_write.h5 +test_f +*.h5 trexio_test/ diff --git a/src/Makefile b/src/Makefile index 2222872..7cac3bc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,10 @@ ifeq ($(COMPILER),GNU) CC=gcc -g CFLAGS=-fPIC -fexceptions -Wall -Werror -Wpedantic -Wextra -LIBS= -L/usr/lib/x86_64-linux-gnu/hdf5/serial/ -lz -lm -lhdf5 -lhdf5_hl #-lgfortran +FS=gfortran -g +FFLAGS=-fPIC -fcheck=all -Waliasing -Wampersand -Wconversion -Wsurprising -Wintrinsics-std -Wno-tabs -Wintrinsic-shadow -Wline-truncation -Wreal-q-constant -Wuninitialized -fbacktrace -ffpe-trap=zero,overflow,underflow -finit-real=nan + +LIBS= -L/usr/lib/x86_64-linux-gnu/hdf5/serial/ -lz -lm -lhdf5 -lhdf5_hl -lgfortran INCLUDE = -I/usr/include/hdf5/serial endif @@ -31,23 +34,36 @@ FFLAGS=fPIC -g -O2 LIBS=-lm endif +RM=rm -f OBJECT_FILES= trexio.o trexio_text.o trexio_hdf5.o HEADER_FILES= trexio.h trexio_text.h trexio_hdf5.h trexio_s.h -export CC CFLAGS LIBS +export CC CFLAGS FC FFLAGS LIBS .PHONY: clean libtrexio.so: $(OBJECT_FILES) $(HEADER_FILES) $(CC) -shared $(OBJECT_FILES) -o libtrexio.so -test: libtrexio.so test.c - $(CC) $(CFLAGS) $(INCLUDE) -Wl,-rpath,$(PWD) -L. test.c -ltrexio $(LIBS) -o test +fortran: libtrexio.so trexio_f.f90 + $(FC) $(FFLAGS) -c trexio_f.f90 -o trexio_f.o + +test_c: libtrexio.so test.c + $(CC) $(CFLAGS) $(INCLUDE) -Wl,-rpath,$(PWD) -L. test.c -ltrexio $(LIBS) -o test_c + +test_f: libtrexio.so test.f90 trexio_f.o + $(CC) $(CFLAGS) $(INCLUDE) -Wl,-rpath,$(PWD) -L. test.f90 trexio_f.o -ltrexio $(LIBS) -o test_f + +test: test_c test_f + $(RM) -r trexio_test + $(RM) -r trexio_test_fort + ./test_c + ./test_f clean: - rm -f *.o libtrexio.so test test_*.h5 - rm -r trexio_test/ + $(RM) *.o libtrexio.so test_*.h5 test_f test_c + $(RM) -r trexio_test/ trexio_test_fort/ %.o: %.c $(HEADER_FILES) $(CC) $(CFLAGS) $(INCLUDE) -c $*.c -o $*.o diff --git a/src/build_trex.sh b/src/build_trex.sh index 8d7b0ca..c10636f 100755 --- a/src/build_trex.sh +++ b/src/build_trex.sh @@ -17,7 +17,7 @@ mkdir -p templates_hdf5/populated # not options. It is safer. echo "remove existing templates" -rm -f -- templates_front/*.{c,h} +rm -f -- templates_front/*.{c,h,f90} rm -f -- templates_text/*.{c,h} rm -f -- templates_hdf5/*.{c,h} diff --git a/src/generator.py b/src/generator.py index 973de2c..420523d 100644 --- a/src/generator.py +++ b/src/generator.py @@ -82,6 +82,7 @@ templ_path_front = join(fileDir,'templates_front') files_exclude = ['prefix_hdf5.c', 'prefix_hdf5.h', 'suffix_hdf5.h', 'prefix_text.c', 'prefix_text.h', 'suffix_text.h', 'prefix_front.c', 'prefix_front.h', 'suffix_front.h', + 'prefix_fortran.f90', 'suffix_fortran.f90', 'prefix_s_front.h', 'suffix_s_front.h', 'templator_front.org', 'templator_hdf5.org', 'templator_text.org'] @@ -259,12 +260,16 @@ for fname in files_funcs_dsets: if params['dtype'] == 'double': h5_dtype = 'double' + f_dtype = 'real(8)' elif params['dtype'] == 'int64_t': h5_dtype = 'long' + f_dtype = 'integer(8)' templine1 = templine2.replace('$group_dset_h5_dtype$', h5_dtype) templine2 = templine1.replace('$group_dset_h5_dtype$'.upper(), h5_dtype.upper()) + templine1 = templine2.replace('$group_dset_f_dtype$', f_dtype) + templine2 = templine1.replace('$group_dset_f_dtype$'.upper(), f_dtype.upper()) templine1 = templine2.replace('$group_dset_rank$', str(params['rank'])) templine2 = templine1 diff --git a/src/templates_front/build.sh b/src/templates_front/build.sh index 5a37440..f20f78a 100644 --- a/src/templates_front/build.sh +++ b/src/templates_front/build.sh @@ -1,15 +1,20 @@ #!/bin/bash -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +# prefixes +cat prefix_front.c > trexio.c +cat prefix_front.h > trexio.h +cat prefix_s_front.h > trexio_s.h +cat prefix_fortran.f90 > trexio_f.f90 -cat $DIR/prefix_front.c > trexio.c -cat $DIR/prefix_front.h > trexio.h -cat $DIR/prefix_s_front.h > trexio_s.h +# c front end +cat populated/pop_*.c >> trexio.c +cat populated/pop_*.h >> trexio.h -cat $DIR/populated/pop_*.c >> trexio.c -cat $DIR/populated/pop_*.h >> trexio.h - -cat $DIR/suffix_s_front.h >> trexio_s.h -cat $DIR/suffix_front.h >> trexio.h +# fortran front end +cat populated/pop_*.f90 >> trexio_f.f90 +# suffixes +cat suffix_s_front.h >> trexio_s.h +cat suffix_front.h >> trexio.h +cat suffix_fortran.f90 >> trexio_f.f90 diff --git a/src/templates_front/templator_front.org b/src/templates_front/templator_front.org index 278de8d..6b00cd1 100644 --- a/src/templates_front/templator_front.org +++ b/src/templates_front/templator_front.org @@ -2,17 +2,29 @@ * Constant file prefixes (not used by generator) :noxport: -** Prefixes - #+NAME:header #+begin_src c -/* This file was generated from the trexio.org org-mode file. +/* This file was generated from the templator_front.org org-mode file. To generate it, open trexio.org in Emacs and execute M-x org-babel-tangle */ #+end_src + #+begin_src fortran :tangle prefix_fortran.f90 :noweb yes + +module trexio + + use, intrinsic :: iso_c_binding + implicit none + + integer, parameter :: TREXIO_HDF5 = 0 + integer, parameter :: TREXIO_TEXT = 1 +! integer, parameter :: TREXIO_JSON = 2 + integer, parameter :: TREXIO_INVALID_BACK_END = 3 + + #+end_src + #+begin_src c :tangle prefix_front.h :noweb yes <
> #ifndef _TREXIO_H @@ -80,6 +92,7 @@ #define FREE(X) { free(X) ; (X)=NULL; } #+end_src + * Front end All calls to TREXIO are thread-safe. @@ -175,7 +188,7 @@ struct trexio_back_end_s { #+end_src ** File opening - + #+begin_src c :tangle prefix_front.h trexio_t* trexio_open(const char* file_name, const char mode, const back_end_t back_end); #+end_src @@ -279,9 +292,20 @@ trexio_t* trexio_open(const char* file_name, const char mode, const back_end_t b return result; } #+end_src + + #+begin_src fortran :tangle prefix_fortran.f90 +interface + integer(8) function trexio_open_c (filename, mode, backend) bind(C, name="trexio_open") + use, intrinsic :: iso_c_binding + character(kind=c_char), dimension(*) :: filename + character, intent(in), value :: mode + integer, intent(in), value :: backend + end function trexio_open_c +end interface + #+end_src ** File closing - + #+begin_src c :tangle prefix_front.h trexio_exit_code trexio_close(trexio_t* file); #+end_src @@ -354,9 +378,16 @@ trexio_exit_code trexio_close(trexio_t* file) { } #+end_src + #+begin_src fortran :tangle prefix_fortran.f90 +interface + integer function trexio_close (trex_file) bind(C) + use, intrinsic :: iso_c_binding + integer(8), intent(in), value :: trex_file + end function trexio_close +end interface + #+end_src * Templates for front end - ** Template for frontend read/write a number #+begin_src c :tangle rw_num_front.h @@ -424,6 +455,32 @@ trexio_exit_code trexio_write_$group_num$(trexio_t* file, const int64_t num) { #+end_src + #+begin_src fortran :tangle write_num_front_fortran.f90 + +interface + integer function trexio_write_$group_num$ (trex_file, num) bind(C) + use, intrinsic :: iso_c_binding + integer(8), intent(in), value :: trex_file + integer(8), intent(in), value :: num + end function trexio_write_$group_num$ +end interface + + #+end_src + + + #+begin_src fortran :tangle read_num_front_fortran.f90 + +interface + integer function trexio_read_$group_num$ (trex_file, num) bind(C) + use, intrinsic :: iso_c_binding + integer(8), intent(in), value :: trex_file + integer(8), intent(out) :: num + end function trexio_read_$group_num$ +end interface + + #+end_src + + ** Template for frontend read/write a dataset #+begin_src c :tangle rw_dset_front.h @@ -531,7 +588,30 @@ trexio_exit_code trexio_write_$group$_$group_dset$(trexio_t* file, const $group_ } } #+end_src - + + #+begin_src fortran :tangle write_dset_front_fortran.f90 + +interface + integer function trexio_write_$group$_$group_dset$ (trex_file, dset) bind(C) + use, intrinsic :: iso_c_binding + integer(8), intent(in), value :: trex_file + $group_dset_f_dtype$, intent(in) :: dset(*) + end function trexio_write_$group$_$group_dset$ +end interface + + #+end_src + + #+begin_src fortran :tangle read_dset_front_fortran.f90 + +interface + integer function trexio_read_$group$_$group_dset$ (trex_file, dset) bind(C) + use, intrinsic :: iso_c_binding + integer(8), intent(in), value :: trex_file + $group_dset_f_dtype$, intent(out) :: dset(*) + end function trexio_read_$group$_$group_dset$ +end interface + + #+end_src * Back ends @@ -541,6 +621,25 @@ trexio_exit_code trexio_write_$group$_$group_dset$(trexio_t* file, const $group_ - Text files: not to be used for production, but useful for debugging - JSON: for portability + +* Fortran helper/wrapper functions + + #+begin_src fortran :tangle suffix_fortran.f90 +contains + integer(8) function trexio_open (filename, mode, backend) + use, intrinsic :: iso_c_binding + implicit none + character(len=*) :: filename + character, intent(in), value :: mode + integer, intent(in), value :: backend + character(len=len_trim(filename)+1) :: filename_c + + filename_c = trim(filename) // c_null_char + trexio_open = trexio_open_c(filename_c, mode, backend) + end function trexio_open + #+end_src + + * File suffixes :noxport: #+begin_src c :tangle suffix_front.h @@ -551,5 +650,9 @@ trexio_exit_code trexio_write_$group$_$group_dset$(trexio_t* file, const $group_ #endif #+end_src + #+begin_src fortran :tangle suffix_fortran.f90 +end module trexio + #+end_src + diff --git a/src/templates_hdf5/build.sh b/src/templates_hdf5/build.sh index 213bdb3..e9bb94b 100644 --- a/src/templates_hdf5/build.sh +++ b/src/templates_hdf5/build.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash cat prefix_hdf5.c > trexio_hdf5.c cat prefix_hdf5.h > trexio_hdf5.h diff --git a/src/templates_text/build.sh b/src/templates_text/build.sh index 2835dd3..e8e1918 100644 --- a/src/templates_text/build.sh +++ b/src/templates_text/build.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash cat prefix_text.c > trexio_text.c cat prefix_text.h > trexio_text.h diff --git a/src/test.f90 b/src/test.f90 new file mode 100644 index 0000000..1116b08 --- /dev/null +++ b/src/test.f90 @@ -0,0 +1,106 @@ +program test_trexio + + call test_write() + call test_read() + +end program test_trexio + +subroutine test_write() + + use trexio + use, intrinsic :: iso_c_binding + implicit none + + integer(8) :: trex_file + + integer :: rc = 1 + integer(8) :: num + + double precision :: charge(12) + double precision :: coord(36) + + num = 12 + charge = (/6., 6., 6., 6., 6., 6., 1., 1., 1., 1., 1., 1. /) + coord = (/ 0.00000000 , 1.39250319 , 0.00000000 , & + -1.20594314 , 0.69625160 , 0.00000000 , & + -1.20594314 , -0.69625160 , 0.00000000 , & + 0.00000000 , -1.39250319 , 0.00000000 , & + 1.20594314 , -0.69625160 , 0.00000000 , & + 1.20594314 , 0.69625160 , 0.00000000 , & + -2.14171677 , 1.23652075 , 0.00000000 , & + -2.14171677 , -1.23652075 , 0.00000000 , & + 0.00000000 , -2.47304151 , 0.00000000 , & + 2.14171677 , -1.23652075 , 0.00000000 , & + 2.14171677 , 1.23652075 , 0.00000000 , & + 0.00000000 , 2.47304151 , 0.00000000 /) + +! trex_file = trexio_open('trexio_test_fort', 'w', TREXIO_TEXT) + trex_file = trexio_open('test_hdf5_fort.h5', 'w', TREXIO_HDF5) + + rc = trexio_write_nucleus_num(trex_file, num) + if (rc == 0) write(*,*) 'SUCCESS WRITE NUM' + + rc = trexio_write_nucleus_charge(trex_file, charge) + if (rc == 0) write(*,*) 'SUCCESS WRITE CHARGE' + + rc = trexio_write_nucleus_coord(trex_file, coord) + if (rc == 0) write(*,*) 'SUCCESS WRITE COORD' + + rc = trexio_close(trex_file) + if (rc == 0) write(*,*) 'SUCCESS CLOSE' + +! ---------------------------------- ! +! to modify fiels of existing file: +! text backend -> open with 'w' +! hdf5 backend -> open with 'a' +! ---------------------------------- ! + +!! trex_file = trexio_open('trexio_test_fort', 'w', TREXIO_TEXT); +!! trex_file = trexio_open('test_hdf5_fort.h5', 'a', TREXIO_HDF5) + +! coord(1) = 666.666 + +! rc = trexio_write_nucleus_coord(trex_file,coord) +! if (rc == 0) write(*,*) 'SUCCESS MODIFY COORD' + +! rc = trexio_close(trex_file) +! if (rc == 0) write(*,*) 'SUCCESS CLOSE' + +end subroutine test_write + +subroutine test_read() + + use trexio + use, intrinsic :: iso_c_binding + implicit none + + integer(8) :: trex_file + + integer :: rc = 1 + integer(8) :: num, num_read + + double precision :: charge(12) + double precision :: coord(36) + + num = 12 + +! trex_file = trexio_open('trexio_test_fort', 'r', TREXIO_TEXT) + trex_file = trexio_open('test_hdf5_fort.h5', 'r', TREXIO_HDF5) + + rc = trexio_read_nucleus_num(trex_file, num_read) + + if (rc == 0 .and. num_read == num) write(*,*) 'SUCCESS READ NUM' + + rc = trexio_read_nucleus_charge(trex_file, charge) + + if (rc == 0 .and. (abs (charge(11) - 1.0) < 1.0D-8) ) write(*,*) 'SUCCESS READ CHARGE' + + rc = trexio_read_nucleus_coord(trex_file, coord) + + if (rc == 0 .and. (abs (coord(2) - 1.39250319) < 1.0D-8) ) write(*,*) 'SUCCESS READ COORD' + + rc = trexio_close(trex_file) + if (rc == 0) write(*,*) 'SUCCESS CLOSE' + +end subroutine test_read +