diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml
index 7a23aa0d..0b1298f5 100644
--- a/.github/workflows/actions.yml
+++ b/.github/workflows/actions.yml
@@ -52,10 +52,10 @@ jobs:
./configure --enable-silent-rules
- name: compile TREXIO
- run: make -j 2
+ run: make -j2
- name: check TREXIO
- run: make check
+ run: make -j2 check
- name: create virtual environment
run: |
@@ -82,8 +82,22 @@ jobs:
name: pytrexio-source
path: ./trexio-*.tar.gz
- - name: clean
- run: make clean
+ - name: maintainer clean
+ run: make maintainer-clean
+
+ - name: reconfigure with clang and AddressSanitizer
+ run: |
+ ./autogen.sh
+ ./configure CC=clang-11 CFLAGS="-O2 -fsanitize=address -fno-omit-frame-pointer" LDFLAGS="-fsanitize=address" --enable-silent-rules
+
+ - name: recompile TREXIO
+ run: make -j2
+
+ - name: recheck TREXIO for memory leaks
+ run: make -j2 check
+
+ - name: maintainer clean
+ run: make maintainer-clean
trexio_macos:
diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml
index 4f8170c7..672ff126 100644
--- a/.github/workflows/build-wheels.yml
+++ b/.github/workflows/build-wheels.yml
@@ -222,7 +222,7 @@ jobs:
#- name: Publish distribution 📦 to Test PyPI
# uses: pypa/gh-action-pypi-publish@master
- # with:
+ # with:
# password: ${{ secrets.TEST_PYPI_API_TOKEN }}
# repository_url: https://test.pypi.org/legacy/
#verbose: true
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 00000000..fd16ba2d
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,10 @@
+# See https://pre-commit.com for more information
+# See https://pre-commit.com/hooks.html for more hooks
+repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v3.2.0
+ hooks:
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ - id: check-yaml
+ - id: check-added-large-files
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 79da12b6..ba6f6c6f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16)
# Initialize the CMake project.
project(Trexio
- VERSION 2.2.1
+ VERSION 2.3.0
DESCRIPTION "TREX I/O library"
LANGUAGES C Fortran
)
diff --git a/ChangeLog b/ChangeLog
index 13e97294..e3bb2174 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,17 @@
CHANGES
=======
+2.3
+---
+
+- Added trexio_to_bitfield_list functionality
+- Added `trexio_has_group` functionality
+- Added OCaml binding
+- Added spin and energy in MOs
+- Added CSF group
+- Added `trexio_flush` functionality
+- Optional compilation `--without-fortran`
+
2.2
---
diff --git a/Makefile.am b/Makefile.am
index 1513ff7e..c05072dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,7 +34,11 @@
ACLOCAL_AMFLAGS = -I m4
CLEANFILES = trexio.mod
+if HAVE_FORTRAN
BUILT_SOURCES = trexio.mod
+else
+BUILT_SOURCES =
+endif
EXTRA_DIST = .git_hash
PACKAGE_VERSION = @PACKAGE_VERSION@
@@ -45,10 +49,13 @@ pkgconfig_DATA = pkgconfig/trexio.pc
# =============== BUILD =============== #
-trexio_h = $(srcdir)/include/trexio.h
-trexio_f = $(srcdir)/include/trexio_f.f90
+trexio_h = include/trexio.h
+include_HEADERS = $(trexio_h)
-include_HEADERS = $(trexio_h) $(trexio_f)
+if HAVE_FORTRAN
+trexio_f = include/trexio_f.f90
+include_HEADERS += $(trexio_f)
+endif
AM_CPPFLAGS = -I$(srcdir)/src -I$(srcdir)/include
@@ -56,7 +63,6 @@ lib_LTLIBRARIES = src/libtrexio.la
SOURCES = \
- $(trexio_h) \
src/trexio.c \
src/trexio_private.h \
src/trexio_s.h \
@@ -75,7 +81,7 @@ ORG_FILES = \
trex.org
-src_libtrexio_la_SOURCES = $(SOURCES)
+src_libtrexio_la_SOURCES = $(trexio_h) $(SOURCES)
# Include CMake-related files in the distribution.
EXTRA_DIST += CMakeLists.txt \
@@ -117,17 +123,20 @@ TESTS_C += \
tests/overwrite_all_hdf5
endif
-TESTS_F = \
- tests/test_f
+TESTS = $(TESTS_C)
+
+if HAVE_FORTRAN
+TESTS_F = tests/test_f
+TESTS += $(TESTS_F)
+endif
-TESTS = $(TESTS_C) $(TESTS_F)
check_PROGRAMS = $(TESTS)
# specify common LDADD options for all tests
LDADD = src/libtrexio.la
-test_trexio_f = $(srcdir)/tests/trexio_f.f90
-CLEANFILES += $(test_trexio_f)
+if HAVE_FORTRAN
+test_trexio_f = tests/trexio_f.f90
$(test_trexio_f): $(trexio_f)
cp $(trexio_f) $(test_trexio_f)
@@ -135,10 +144,16 @@ $(test_trexio_f): $(trexio_f)
trexio.mod: tests/trexio_f.o
tests_test_f_SOURCES = $(test_trexio_f) tests/test_f.f90
+endif
clean-local:
-rm -rf -- *.dir/ *.h5 __pycache__/
+# =============== GUIX MANIFEST =============== #
+
+trexio_scm = $(srcdir)/tools/trexio.scm
+EXTRA_DIST += $(trexio_scm)
+
# =============== DOCUMENTATION =============== #
HTML_TANGLED = docs/index.html \
@@ -176,9 +191,15 @@ HDF5_CPPFLAGS = @HDF5_CPPFLAGS@
if TREXIO_DEVEL
-CLEANFILES += $(SOURCES) $(trexio_f) $(trexio_h) $(HTML_TANGLED) $(htmlizer) .git_hash
+CLEANFILES += $(SOURCES) $(trexio_h) $(HTML_TANGLED) $(htmlizer) .git_hash
-BUILT_SOURCES += $(SOURCES) $(trexio_f) $(test_trexio_f)
+BUILT_SOURCES += $(SOURCES) $(trexio_h)
+
+if HAVE_FORTRAN
+CLEANFILES += $(trexio_f)
+BUILT_SOURCES += $(trexio_f) $(test_trexio_f)
+$(trexio_f): $(trexio_h)
+endif
.git_hash: FORCE
git log | head -1 | cut -d ' ' -f 2 > .git_hash
@@ -188,10 +209,10 @@ all: .git_hash
GENERATOR_FILES = $(srcdir)/tools/generator.py \
$(srcdir)/tools/generator_tools.py
-$(SOURCES): $(trexio_f)
+$(SOURCES): $(trexio_h)
src/trexio.c: $(trexio_h)
-$(trexio_f): $(ORG_FILES) $(GENERATOR_FILES)
+$(trexio_h): $(ORG_FILES) $(GENERATOR_FILES)
cd $(srcdir)/tools && ./build_trexio.sh
$(htmlizer): $(ORG_FILES) $(srcdir)/src/README.org
@@ -208,6 +229,22 @@ cppcheck.out: $(trexio_h)
--language=c --std=c99 -rp --platform=unix64 \
-I../include *.c *.h 2>../$@
+#################
+# OCaml binding #
+#################
+
+ocaml/trexio/_build/default/lib/trexio.cma:
+ $(MAKE) -C ocaml/trexio
+
+ocaml: ocaml/trexio/_build/default/lib/trexio.cma
+
+ocaml-install: ocaml/trexio/_build/default/lib/trexio.cma
+ opam install ocaml/trexio
+
+##################
+# Python binding #
+##################
+
setup_py = $(srcdir)/python/setup.py
setup_cfg = $(srcdir)/python/setup.cfg
pytrexio_py = $(srcdir)/python/pytrexio/pytrexio.py
@@ -277,6 +314,6 @@ CLEANFILES += $(pytrexio_c) \
python/src/*.c \
python/src/*.h
-.PHONY: cppcheck python-test python-install python-sdist check-numpy FORCE
+.PHONY: cppcheck python-test python-install python-sdist check-numpy FORCE ocaml
endif
diff --git a/README.md b/README.md
index 91b1889f..9d5c3644 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
# TREXIO
+
[![build](https://github.com/TREX-CoE/trexio/actions/workflows/actions.yml/badge.svg)](https://github.com/TREX-CoE/trexio/actions/workflows/actions.yml)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/TREX-CoE/trexio)
@@ -9,10 +10,10 @@ TREX library for efficient I/O.
## Minimal requirements (for users):
-- Autotools (autoconf >= 2.69, automake >= 1.11, libtool >= 2.2) or CMake (>= 3.16)
+- Autotools (autoconf >= 2.69, automake >= 1.11, libtool >= 2.2) or CMake (>= 3.16)
- C compiler (gcc/icc/clang)
- Fortran compiler (gfortran/ifort)
-- HDF5 library (>= 1.8) [optional, recommended for high performance]
+- HDF5 library (>= 1.8) [optional, recommended for high performance]
## Installation procedure from the tarball (for users):
@@ -63,6 +64,9 @@ The aforementioned instructions rely on [Autotools](https://www.gnu.org/software
## Installation procedure for conda users
+[![Anaconda-Server Badge](https://anaconda.org/conda-forge/trexio/badges/version.svg)](https://anaconda.org/conda-forge/trexio)
+[![Anaconda-Server Badge](https://anaconda.org/conda-forge/trexio/badges/platforms.svg)](https://anaconda.org/conda-forge/trexio)
+
The official releases of TREXIO `>2.0.0` are also available via the `conda-forge` channel.
The pre-compiled stable binaries of `trexio` can be installed as follows:
@@ -73,6 +77,33 @@ conda install trexio -c conda-forge
More details can be found in the corresponding [trexio-feedstock](https://github.com/conda-forge/trexio-feedstock).
Note that both parallel (see `mpi_openmpi` prefix) and serial (`nompi`) variants are provided.
+## Installation procedure for Guix users
+
+The official releases of TREXIO `>=2.0.0` can be installed using the
+[GNU Guix](https://guix.gnu.org) functional package manager.
+The [trexio.scm](https://github.com/TREX-CoE/trexio/blob/master/tools/trexio.scm)
+Schema file contains the manifest specification for the `trexio` package.
+It can be installed within the selected `$GUIX_PROFILE` as follows:
+
+```
+guix package \
+ --profile=$GUIX_PROFILE \
+ --cores= \
+ --install-from-file=trexio.scm
+```
+
+## Installation procedure for Spack users
+
+The official releases `>=2.0.0` and the development version of TREXIO can be installed using the
+[Spack](https://spack.io/) package manager.
+The [trexio/package.py](https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/trexio/package.py)
+file contains the Spack specifications required to build different variants of `trexio` library.
+It can be installed as follows
+
+```
+spack install --jobs trexio
+```
+
## Compilation without the HDF5 library
By default, the configuration step proceeds to search for the [HDF5 library](https://portal.hdfgroup.org/display/HDF5/HDF5).
diff --git a/configure.ac b/configure.ac
index 27d3cd45..a1ef1c59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
-AC_INIT([trexio],[2.2.1],[https://github.com/TREX-CoE/trexio/issues])
+AC_INIT([trexio],[2.3.0],[https://github.com/TREX-CoE/trexio/issues])
AC_CONFIG_SRCDIR([Makefile.in])
AC_CONFIG_HEADERS([include/config.h])
@@ -50,12 +50,18 @@ AS_IF([test "$ac_cv_prog_cc_c99" = "no"],
[AC_MSG_ERROR([The compiler does not support C99])])
AC_PROG_CC_C_O
-# Fortran
-AC_PROG_FC
-AC_FC_FREEFORM
-AC_FC_SRCEXT([f90])
-AC_PROG_FC_C_O
-AC_FC_LIBRARY_LDFLAGS
+
+# Fortran API [default: --with-fortran], do not disable in the dev mode
+AC_ARG_WITH(fortran, [AS_HELP_STRING([--without-fortran],[do not test and install the Fortran API])], ok=$withval, ok=yes)
+if test "$ok" = "yes"; then
+ AC_PROG_FC
+ AC_FC_FREEFORM
+ AC_FC_SRCEXT([f90])
+ AC_PROG_FC_C_O
+ AC_FC_LIBRARY_LDFLAGS
+fi
+
+AM_CONDITIONAL([HAVE_FORTRAN],[test "$ok" = "yes"])
# pkg-config
PKG_PROG_PKG_CONFIG()
@@ -66,6 +72,31 @@ AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_GREP
+# Specific options required with some compilers
+case $FC in
+ *gfortran*)
+ FCFLAGS="$FCFLAGS -fPIC"
+ ;;
+ *flang*)
+ FCFLAGS="$FCFLAGS -fPIC"
+ ;;
+ *ifort*)
+ FCFLAGS="$FCFLAGS -fPIC"
+ ;;
+esac
+
+case $CC in
+ *gcc*)
+ CFLAGS="$CFLAGS -fPIC"
+ ;;
+ *clang*)
+ CFLAGS="$CFLAGS -fPIC"
+ ;;
+ *icc*)
+ CFLAGS="$CFLAGS -fPIC"
+ ;;
+esac
+
## ---------
## Libraries
@@ -138,7 +169,7 @@ AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
# Checks for library functions.
-AC_FUNC_MALLOC
+# AC_FUNC_MALLOC
AC_CHECK_FUNCS([memset mkdir strerror])
if test "x$enable_maintainer_mode" == "xyes"; then
diff --git a/examples.org b/examples.org
index eaa7d58e..241c63ef 100644
--- a/examples.org
+++ b/examples.org
@@ -3,7 +3,8 @@
#+SETUPFILE: docs/theme.setup
-* Accessing sparse quantities
+* Accessing sparse quantities (integrals)
+
** Fortran
:PROPERTIES:
:header-args: :tangle print_energy.f90
@@ -270,3 +271,83 @@ program print_energy
end program
#+end_src
+
+
+* Reading determinants
+
+** Fortran
+ :PROPERTIES:
+ :header-args: :tangle print_dets.f90
+ :END:
+
+ #+begin_src f90
+program test
+
+ use trexio
+ implicit none
+
+ character*(128) :: filename ! Name of the input file
+ integer(trexio_exit_code) :: rc ! Return code for error checking
+ integer(trexio_t) :: trex_determinant_file ! TREXIO file handle
+ character*(128) :: err_msg ! Error message
+
+
+ integer*8, allocatable :: buffer(:,:,:)
+ integer(8) :: offset, icount, BUFSIZE
+ integer :: ndet, int64_num, m
+
+ integer :: occ_num_up, occ_num_dn
+ integer, allocatable :: orb_list_up(:), orb_list_dn(:)
+
+ call getarg(1, filename)
+
+ trex_determinant_file = trexio_open(filename, 'r', TREXIO_AUTO, rc)
+ if (rc /= TREXIO_SUCCESS) then
+ call trexio_string_of_error(rc, err_msg)
+ print *, 'Error opening TREXIO file: '//trim(err_msg)
+ stop
+ end if
+
+ rc = trexio_read_determinant_num(trex_determinant_file, ndet)
+ if (rc /= TREXIO_SUCCESS) then
+ call trexio_string_of_error(rc, err_msg)
+ print *, 'Error reading determinant_num: '//trim(err_msg)
+ stop
+ end if
+ print *, 'ndet', ndet
+
+ rc = trexio_get_int64_num(trex_determinant_file, int64_num)
+ if (rc /= TREXIO_SUCCESS) then
+ call trexio_string_of_error(rc, err_msg)
+ print *, 'Error reading int64_num: '//trim(err_msg)
+ stop
+ end if
+ print *, 'int64_num', int64_num
+
+ BUFSIZE = 1000_8
+ allocate(buffer(int64_num, 2, BUFSIZE))
+ allocate(orb_list_up(int64_num*64), orb_list_dn(int64_num*64))
+
+ offset = 0_8
+ icount = BUFSIZE
+ do while (icount == BUFSIZE)
+ if (offset < ndet) then
+ rc = trexio_read_determinant_list(trex_determinant_file, offset, icount, buffer)
+ offset = offset + icount
+ else
+ icount = 0
+ end if
+ print *, '---'
+ do m=1,icount
+ rc = trexio_to_orbital_list_up_dn(int64_num, buffer(1,1,m), &
+ orb_list_up, orb_list_dn, occ_num_up, occ_num_dn)
+ print '(100(I3,X))', (orb_list_up(1:occ_num_up)), (orb_list_dn(1:occ_num_dn))
+ print *, ''
+ end do
+ end do
+
+ deallocate(buffer, orb_list_dn, orb_list_up)
+
+end
+ #+end_src
+
diff --git a/m4/ax_lib_hdf5.m4 b/m4/ax_lib_hdf5.m4
index 074c2a82..86f97fb8 100644
--- a/m4/ax_lib_hdf5.m4
+++ b/m4/ax_lib_hdf5.m4
@@ -257,7 +257,7 @@ HDF5 support is being disabled (equivalent to --with-hdf5=no).
AC_MSG_WARN([Unable to compile HDF5 test program])
fi
dnl Look for HDF5's high level library
- AC_HAVE_LIBRARY([hdf5_hl], [HDF5_LIBS="-lhdf5_hl $HDF5_LIBS"], [], [])
+ AC_CHECK_LIB([hdf5_hl], [main],[HDF5_LIBS="-lhdf5_hl $HDF5_LIBS"], [], [])
CC=$ax_lib_hdf5_save_CC
CPPFLAGS=$ax_lib_hdf5_save_CPPFLAGS
diff --git a/ocaml/trexio/.ocamlinit b/ocaml/trexio/.ocamlinit
new file mode 100644
index 00000000..e1a4ac5d
--- /dev/null
+++ b/ocaml/trexio/.ocamlinit
@@ -0,0 +1,3 @@
+#use "topfind";;
+open Printf;;
+
diff --git a/ocaml/trexio/Makefile b/ocaml/trexio/Makefile
new file mode 100644
index 00000000..91d0b694
--- /dev/null
+++ b/ocaml/trexio/Makefile
@@ -0,0 +1,9 @@
+default: sources
+ dune build
+
+lib/trexio.ml: ../../trex.json read_json.py src/trexio.ml src/trexio.mli src/trexio_stubs.c
+ ./read_json.py
+
+sources: lib/trexio.ml
+
+.PHONY: sources default
diff --git a/ocaml/trexio/README.md b/ocaml/trexio/README.md
new file mode 100644
index 00000000..a1bc2fa5
--- /dev/null
+++ b/ocaml/trexio/README.md
@@ -0,0 +1,9 @@
+# TREXIO OCaml interface
+
+## Building the source code
+
+The hand-written source files are located in the `src` directory. These files contain
+the pieces of code that can't be generated automatically. The source code distributed
+in the OPAM package is generated by the `read_json.py` script, and is written in files
+located in the `lib` directory.
+
diff --git a/ocaml/trexio/dune-project b/ocaml/trexio/dune-project
new file mode 100644
index 00000000..7793cce6
--- /dev/null
+++ b/ocaml/trexio/dune-project
@@ -0,0 +1,36 @@
+(lang dune 3.1)
+
+(name trexio)
+(version 2.3.0)
+
+(generate_opam_files true)
+
+(source
+ (github trex-coe/trexio_ocaml))
+
+(authors
+ "Anthony Scemama "
+ "Evgeny Posenitskiy "
+)
+
+(maintainers
+ "Anthony Scemama "
+)
+
+(license "BSD-3-Clause")
+
+(documentation "https://trex-coe.github.io/trexio/")
+
+(package
+ (name trexio)
+ (synopsis "Binding for the TREXIO Input/Output library")
+ (description "TREXIO is a file format and library for storing wave functions and integrals for quantum chemistry.")
+ (depends
+ dune
+ (dune-configurator :build)
+ (conf-pkg-config :build))
+ (tags
+ ("Quantum chemistry" "Library"))
+)
+
+; See the complete stanza docs at https://dune.readthedocs.io/en/stable/dune-files.html#dune-project
diff --git a/ocaml/trexio/lib/config/discover.ml b/ocaml/trexio/lib/config/discover.ml
new file mode 100644
index 00000000..4362729e
--- /dev/null
+++ b/ocaml/trexio/lib/config/discover.ml
@@ -0,0 +1,22 @@
+module C = Configurator.V1
+
+let () =
+C.main ~name:"trexio" (fun c ->
+let default : C.Pkg_config.package_conf =
+ { libs = ["-ltrexio"]
+ ; cflags = ["-fPIC"]
+ }
+in
+let conf =
+ match C.Pkg_config.get c with
+ | None -> default
+ | Some pc ->
+ match (C.Pkg_config.query pc ~package:"trexio") with
+ | None -> default
+ | Some deps -> deps
+in
+
+
+C.Flags.write_sexp "c_flags.sexp" conf.cflags;
+C.Flags.write_sexp "c_library_flags.sexp" conf.libs)
+
diff --git a/ocaml/trexio/lib/config/dune b/ocaml/trexio/lib/config/dune
new file mode 100644
index 00000000..187bd5e1
--- /dev/null
+++ b/ocaml/trexio/lib/config/dune
@@ -0,0 +1,3 @@
+(executable
+ (name discover)
+ (libraries dune-configurator))
diff --git a/ocaml/trexio/lib/dune b/ocaml/trexio/lib/dune
new file mode 100644
index 00000000..d2ff2605
--- /dev/null
+++ b/ocaml/trexio/lib/dune
@@ -0,0 +1,19 @@
+(library
+ (name trexio)
+ (public_name trexio)
+ (foreign_stubs
+ (language c)
+ (names trexio_stubs)
+ (flags (:include c_flags.sexp) "-fPIC"))
+ (c_library_flags (:include c_library_flags.sexp))
+)
+
+(rule
+ (targets c_flags.sexp c_library_flags.sexp)
+ (action (run ./config/discover.exe)))
+
+(env
+ (dev
+ (flags ))
+ (release
+ (ocamlopt_flags )))
diff --git a/ocaml/trexio/read_json.py b/ocaml/trexio/read_json.py
new file mode 100755
index 00000000..d41bc00a
--- /dev/null
+++ b/ocaml/trexio/read_json.py
@@ -0,0 +1,659 @@
+#!/usr/bin/env python
+
+import json
+
+json_file = "../../trex.json"
+stubs_file= "trexio_stubs.c"
+ml_file = "trexio.ml"
+mli_file = ml_file+"i"
+
+def write_stubs(data):
+
+ with open("src/"+stubs_file,'r') as f:
+ content = f.readlines()
+ index = -1
+ for i, line in enumerate(content):
+ if line.startswith("/**** ****/"):
+ index = i
+ break
+ content_pre = ''.join(content[:index])
+ content_post = ''.join(content[index:])
+
+ with open("lib/"+stubs_file,'w') as f:
+ f.write(content_pre)
+
+ for group in data:
+ t = """
+CAMLprim value caml_delete_{group}(value file)
+{
+ CAMLparam1(file);
+ trexio_exit_code rc = trexio_delete_{group}( File_val(file) );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_unit );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+CAMLprim value caml_has_{group}(value file)
+{
+ CAMLparam1(file);
+ trexio_exit_code rc = trexio_has_{group}( File_val(file) );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_bool(true) );
+ } else {
+ CAMLreturn ( Val_bool(false) );
+ }
+}
+"""
+ f.write( t.replace("{group}",group) )
+
+ for element in data[group]:
+ t = """
+CAMLprim value caml_has_{group}_{element}(value file)
+{
+ CAMLparam1(file);
+ trexio_exit_code rc = trexio_has_{group}_{element}( File_val(file) );
+ CAMLreturn ( Val_bool(rc == TREXIO_SUCCESS) );
+}
+"""
+ f.write( t.replace("{group}", group)
+ .replace("{element}", element) )
+
+ # Scalar elements
+ if data[group][element][1] == []:
+
+ if data[group][element][0] in [ "int", "dim", "index" ]:
+ t = """
+CAMLprim value caml_read_{group}_{element}(value file)
+{
+ CAMLparam1(file);
+ int64_t result;
+ trexio_exit_code rc = trexio_read_{group}_{element}_64( File_val(file), &result );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_int(result) );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+CAMLprim value caml_write_{group}_{element}(value file, value data)
+{
+ CAMLparam2(file, data);
+ trexio_exit_code rc = trexio_write_{group}_{element}_64( File_val(file), (int64_t) Int_val(data) );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_unit );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+"""
+ f.write( t.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ elif data[group][element][0] in [ "float" ]:
+ t = """
+CAMLprim value caml_read_{group}_{element}(value file)
+{
+ CAMLparam1(file);
+ double result;
+ trexio_exit_code rc = trexio_read_{group}_{element}_64( File_val(file), &result );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( caml_copy_double(result) );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+CAMLprim value caml_write_{group}_{element}(value file, value data)
+{
+ CAMLparam2(file, data);
+ trexio_exit_code rc = trexio_write_{group}_{element}_64( File_val(file), (double) Double_val(data) );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_unit );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+"""
+ f.write( t.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ elif data[group][element][0] in [ "string" ]:
+ t = """
+CAMLprim value caml_read_{group}_{element}(value file, value max_str_len_in)
+{
+ CAMLparam2(file, max_str_len_in);
+ int32_t max_str_len = Int_val(max_str_len_in);
+ char result[max_str_len];
+ trexio_exit_code rc = trexio_read_{group}_{element}( File_val(file), result, max_str_len);
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( caml_copy_string(result) );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+CAMLprim value caml_write_{group}_{element}(value file, value data)
+{
+ CAMLparam2(file, data);
+ const char* val = String_val(data);
+ trexio_exit_code rc = trexio_write_{group}_{element}( File_val(file), val, (int32_t) strlen(val));
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_unit );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+"""
+ f.write( t.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ if data[group][element][0] in [ "dim readonly" ]:
+ t = """
+CAMLprim value caml_read_{group}_{element}(value file)
+{
+ CAMLparam1(file);
+ int64_t result;
+ trexio_exit_code rc = trexio_read_{group}_{element}_64( File_val(file), &result );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_int(result) );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+"""
+ f.write( t.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0].split()[0]) )
+
+ # Array elements
+ else:
+
+ if data[group][element][0] in [ "float" ]:
+ t = """
+CAMLprim value caml_read_safe_{group}_{element}(value file_in, value size_max_in)
+{
+ CAMLparam2 ( file_in, size_max_in );
+ CAMLlocal1 ( result );
+
+ trexio_t* file = File_val( file_in );
+ int64_t size_max = (int64_t) Int_val(size_max_in);
+
+ double* read_data = (double*) malloc (size_max * sizeof(double));
+ trexio_exit_code rc = trexio_read_safe_{group}_{element}_64(file, read_data, size_max);
+ if (rc != TREXIO_SUCCESS) {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+
+ result = caml_alloc(size_max * Double_wosize, Double_array_tag);
+ for (size_t i=0 ; i bool\n"
+ f.write( t.replace("{group}",group) )
+
+ for element in data[group]:
+ t = "val has_{group}_{element}: trexio_file -> bool\n"
+ f.write( t.replace("{group}", group)
+ .replace("{element}", element) )
+
+ # Scalar elements
+ if data[group][element][1] == []:
+
+ if data[group][element][0] in [ "int", "float", "dim", "index" ]:
+ t = [ "val read_{group}_{element} : trexio_file -> {type}\n" ,
+ "val write_{group}_{element}: trexio_file -> {type} -> unit\n" ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ elif data[group][element][0] in [ "string" ]:
+ t = [ "val read_{group}_{element} : ?max_str_len:int -> trexio_file -> {type}\n" ,
+ "val write_{group}_{element}: trexio_file -> {type} -> unit\n" ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ elif data[group][element][0] in [ "dim readonly" ]:
+ t = [ "val read_{group}_{element} : trexio_file -> {type}\n" ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0].split()[0]) )
+
+ # Arrays
+ else:
+
+ if data[group][element][0] in [ "int", "float", "dim", "index" ]:
+ t = [ "val read_safe_{group}_{element} : trexio_file -> int -> {type} array\n" ,
+ "val write_safe_{group}_{element}: trexio_file -> int -> {type} array -> unit\n"
+ "val read_{group}_{element} : trexio_file -> {type} array\n" ,
+ "val write_{group}_{element}: trexio_file -> {type} array -> unit\n"
+]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ elif data[group][element][0] in [ "string" ]:
+ t = [ "val read_safe_{group}_{element} : trexio_file -> int -> int -> {type} array\n" ,
+ "val write_safe_{group}_{element}: trexio_file -> int -> int -> {type} array -> unit\n"
+ "val read_{group}_{element} : ?max_str_len:int -> trexio_file -> {type} array\n" ,
+ "val write_{group}_{element}: trexio_file -> {type} array -> unit\n"
+]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ elif data[group][element][0] in [ "float sparse" ]:
+ size = len(data[group][element][1])
+ typ = "(" + "*".join( [ "int" for _ in range(size) ]) + " * float) array"
+ t = [ "val read_{group}_{element} : trexio_file -> offset:dim -> buffer_size:dim -> {type}\n" ,
+ "val write_{group}_{element} : trexio_file -> offset:dim -> {type} -> unit\n" ,
+ ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", typ) )
+
+ f.write(content_post)
+
+
+def write_ml(data):
+
+ with open("src/"+ml_file,'r') as f:
+ content = f.readlines()
+ index = -1
+ for i, line in enumerate(content):
+ if line.startswith("(**** ****)"):
+ index = i
+ break
+ content_pre = ''.join(content[:index])
+ content_post = ''.join(content[index:])
+
+ with open("lib/"+ml_file,'w') as f:
+ f.write(content_pre)
+
+ for group in data:
+ t = "external delete_{group}: trexio_file -> unit = \"caml_delete_{group}\"\n"
+ t += "external has_{group}: trexio_file -> bool = \"caml_has_{group}\"\n"
+ f.write( t.replace("{group}",group) )
+
+ for element in data[group]:
+ t = "external has_{group}_{element}: trexio_file -> bool = \"caml_has_{group}_{element}\"\n"
+ f.write( t.replace("{group}", group)
+ .replace("{element}", element) )
+
+ # Scalar elements
+ if data[group][element][1] == []:
+
+ if data[group][element][0] in [ "int", "float", "dim", "index" ]:
+ t = [ "external read_{group}_{element} : trexio_file -> {type} = \"caml_read_{group}_{element}\"\n" ,
+ "external write_{group}_{element}: trexio_file -> {type} -> unit = \"caml_write_{group}_{element}\"\n" ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ if data[group][element][0] in [ "string" ]:
+ t = [ "external read_{group}_{element}_c : trexio_file -> int -> {type} = \"caml_read_{group}_{element}\"\n" ,
+ "let read_{group}_{element} ?(max_str_len=8192) f = read_{group}_{element}_c f max_str_len\n",
+ "external write_{group}_{element}: trexio_file -> {type} -> unit = \"caml_write_{group}_{element}\"\n" ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ elif data[group][element][0] in [ "dim readonly" ]:
+ t = [ "external read_{group}_{element} : trexio_file -> {type} = \"caml_read_{group}_{element}\"\n" ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0].split()[0]) )
+
+ # Arrays
+ else:
+
+ if data[group][element][0] in [ "int", "float", "dim", "index" ]:
+ t = [ "external read_safe_{group}_{element} : trexio_file -> int -> {type} array = \"caml_read_safe_{group}_{element}\"\n" ,
+ "external write_safe_{group}_{element}: trexio_file -> int -> {type} array -> unit = \"caml_write_safe_{group}_{element}\"\n",
+ "let read_{group}_{element} f = \n let size = 1 in \n"]
+ t_prime = []
+ for dim in data[group][element][1]:
+ try: # A dimensioning variable
+ dim_group, dim_element = dim.split('.')
+ t_prime += [f" let size = size * read_{dim_group}_{dim_element} f in\n"]
+ except: # Only an integer
+ t_prime += [f" let size = size * {dim} in\n"]
+
+ t += t_prime
+ t += [ " read_safe_{group}_{element} f size\n\n" ]
+ t += [ "let write_{group}_{element} f a = \n let size = 1 in \n"]
+ t += t_prime
+ t += [ " write_safe_{group}_{element} f size a\n\n" ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+ elif data[group][element][0] in [ "string" ]:
+ t = [ "external read_safe_{group}_{element} : trexio_file -> int -> int -> {type} array = \"caml_read_safe_{group}_{element}\"\n" ,
+ "external write_safe_{group}_{element}: trexio_file -> int -> int -> {type} array -> unit = \"caml_write_safe_{group}_{element}\"\n",
+ "let read_{group}_{element} ?(max_str_len=1024) f = \n let size = 1 in \n"]
+ t_prime = []
+ for dim in data[group][element][1]:
+ try: # A dimensioning variable
+ dim_group, dim_element = dim.split('.')
+ t_prime += [f" let size = size * read_{dim_group}_{dim_element} f in\n"]
+ except: # Only an integer
+ t_prime += [f" let size = size * {dim} in\n"]
+
+ t += t_prime
+ t += [ " read_safe_{group}_{element} f size max_str_len\n\n" ,
+ "let write_{group}_{element} f a = \n let size = 1 in \n",
+ " let max_str_len = Array.map String.length a\n" ,
+ " |> Array.fold_left (fun x y -> if x>y then x else y) 0\n",
+ " |> (+) 1 in\n" ]
+ t += t_prime
+ t += [ " write_safe_{group}_{element} f size max_str_len a\n\n" ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", data[group][element][0]) )
+
+
+ elif data[group][element][0] in [ "float sparse" ]:
+ size = len(data[group][element][1])
+ typ = "(" + "*".join( [ "int" for _ in range(size) ]) + " * float) array"
+ t = [ "external read_{group}_{element} : trexio_file -> offset:dim -> buffer_size:dim -> {type} = \"caml_read_{group}_{element}\"\n" ,
+ "external write_{group}_{element} : trexio_file -> offset:dim -> {type} -> unit = \"caml_write_{group}_{element}\"\n"
+ ]
+ for i in t:
+ f.write( i.replace("{group}", group)
+ .replace("{element}", element)
+ .replace("{type}", typ) )
+
+ f.write(content_post)
+
+
+
+
+def main():
+
+ with open(json_file,'r') as f:
+ data = json.load(f)
+ for group in data:
+ for element in data[group]:
+ if data[group][element][0] == "str":
+ data[group][element][0] = "string"
+
+ write_ml(data)
+ write_mli(data)
+ write_stubs(data)
+
+if __name__ == "__main__":
+ main()
+
diff --git a/ocaml/trexio/src/trexio.ml b/ocaml/trexio/src/trexio.ml
new file mode 100644
index 00000000..fd2ea41d
--- /dev/null
+++ b/ocaml/trexio/src/trexio.ml
@@ -0,0 +1,37 @@
+
+type trexio_file
+
+type trexio_exit_code = int
+
+type trexio_backend =
+| HDF5
+| TEXT
+| AUTO
+
+type index = int
+type dim = int
+
+external open_file : string -> char -> trexio_backend -> trexio_file = "caml_open_file"
+external close_file : trexio_file -> unit = "caml_close_file"
+external inquire_file : string -> bool = "caml_inquire_file"
+external set_one_based : trexio_file -> unit = "caml_set_one_based"
+external get_state : trexio_file -> int = "caml_get_state"
+external set_state : trexio_file -> int -> unit = "caml_set_state"
+external info : unit -> unit = "caml_info"
+
+external to_orbital_list : Int64.t array -> int list = "caml_to_orbital_list"
+
+
+(**** ****)
+
+external read_determinant_list : trexio_file -> offset:int -> buffer_size:int -> (bytes * bytes) array = "caml_read_determinant_list"
+external write_determinant_list : trexio_file -> offset:int -> (bytes * bytes) array -> unit = "caml_write_determinant_list"
+
+external read_determinant_coefficient : trexio_file -> offset:int -> buffer_size:int -> float array = "caml_read_determinant_coefficient"
+external write_determinant_coefficient : trexio_file -> offset:int -> float array -> unit = "caml_write_determinant_coefficient"
+
+
+let to_orbital_list_up_dn (up,dn) =
+ (to_orbital_list up, to_orbital_list dn)
+
+
diff --git a/ocaml/trexio/src/trexio.mli b/ocaml/trexio/src/trexio.mli
new file mode 100644
index 00000000..e86cfd23
--- /dev/null
+++ b/ocaml/trexio/src/trexio.mli
@@ -0,0 +1,41 @@
+(*
+(** Constants *)
+val package_version : string
+val version_major : int
+val version_minor : int
+val version_patch : int
+val git_hash : string
+*)
+
+(** Open/close *)
+
+type trexio_file
+type trexio_exit_code
+type trexio_backend =
+ | HDF5
+ | TEXT
+ | AUTO
+
+type index = int
+type dim = int
+
+val open_file : string -> char -> trexio_backend -> trexio_file
+val inquire_file : string -> bool
+val close_file : trexio_file -> unit
+val set_one_based : trexio_file -> unit
+val get_state : trexio_file -> int
+val set_state : trexio_file -> int -> unit
+val info : unit -> unit
+
+val to_orbital_list : Int64.t array -> int list
+val to_orbital_list_up_dn : (Int64.t array)*(Int64.t array) -> (int list)*(int list)
+
+(**** ****)
+
+val read_determinant_list : trexio_file -> offset:int -> buffer_size:int -> (bytes * bytes) array
+val write_determinant_list : trexio_file -> offset:int -> (bytes * bytes) array -> unit
+
+val read_determinant_coefficient : trexio_file -> offset:int -> buffer_size:int -> float array
+val write_determinant_coefficient : trexio_file -> offset:int -> float array -> unit
+
+
diff --git a/ocaml/trexio/src/trexio_stubs.c b/ocaml/trexio/src/trexio_stubs.c
new file mode 100644
index 00000000..d459f824
--- /dev/null
+++ b/ocaml/trexio/src/trexio_stubs.c
@@ -0,0 +1,268 @@
+#include
+#include
+#include
+#define CAML_NAME_SPACE
+#include
+#include
+#include
+#include
+#include
+#include
+
+static trexio_t* File_val( value file )
+{
+ return *((trexio_t**) Data_abstract_val(file));
+}
+
+
+CAMLprim value caml_open_file(value filename, value mode, value backend)
+{
+ CAMLparam3(filename, mode, backend);
+
+ trexio_exit_code rc = 0;
+ value v = caml_alloc(1, Abstract_tag);
+
+ trexio_t* result = trexio_open (String_val(filename),
+ Int_val(mode),
+ Int_val(backend),
+ &rc);
+
+ *((trexio_t **) Data_abstract_val(v)) = result;
+
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn( v );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+
+CAMLprim value caml_close_file(value file)
+{
+ CAMLparam1(file);
+ trexio_exit_code rc = trexio_close( File_val(file) );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_unit );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+
+CAMLprim value caml_inquire_file(value filename)
+{
+ CAMLparam1 (filename);
+ trexio_exit_code rc = trexio_inquire( String_val (filename) );
+ CAMLreturn(Val_bool(rc == TREXIO_SUCCESS));
+}
+
+
+CAMLprim value caml_set_one_based(value file)
+{
+ CAMLparam1(file);
+ trexio_exit_code rc = trexio_set_one_based( File_val(file) );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_unit );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+
+CAMLprim value caml_set_state(value file, value state)
+{
+ CAMLparam2(file, state);
+ printf("%d\n", Int_val(state));
+ trexio_exit_code rc = trexio_set_state( File_val(file), (int32_t) Int_val(state) );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_unit );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+
+CAMLprim value caml_get_state(value file)
+{
+ CAMLparam1(file);
+ int32_t result;
+ trexio_exit_code rc = trexio_get_state( File_val(file), &result );
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_int(result) );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+
+CAMLprim value caml_info(value unit)
+{
+ CAMLparam1(unit);
+ trexio_exit_code rc = trexio_info();
+ if (rc == TREXIO_SUCCESS) {
+ CAMLreturn ( Val_unit );
+ } else {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+}
+
+
+CAMLprim value caml_to_orbital_list(value bitfield)
+{
+ CAMLparam1 ( bitfield );
+ CAMLlocal2 ( result, cons );
+
+ int32_t N_int = Wosize_val(bitfield);
+ bitfield_t* d1 = (bitfield_t*) malloc (N_int * sizeof(bitfield_t));
+ for (int i=0 ; i= 0 ; --i) {
+ cons = caml_alloc(2, 0);
+ Store_field(cons, 0, Val_int(list[i])); // head
+ Store_field(cons, 1, result); // head
+ result = cons;
+ }
+
+ free(list);
+ CAMLreturn(result);
+}
+
+
+/**** ****/
+
+CAMLprim value caml_read_determinant_list(value file_in, value offset_in, value buffer_size_in)
+{
+ CAMLparam3 ( file_in, offset_in, buffer_size_in );
+ CAMLlocal4 ( result, detup, detdn, det );
+
+ trexio_t* file = File_val(file_in);
+ int64_t offset = Int_val( offset_in );
+ int64_t buffer_size = Int_val( buffer_size_in );
+
+ int32_t int_num = 0;
+ trexio_exit_code rc = trexio_get_int64_num(file, &int_num);
+ if (rc != TREXIO_SUCCESS) {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+
+ int64_t* buffer = (int64_t*) malloc ( buffer_size * int_num * 2 * sizeof(int64_t) );
+
+ rc = trexio_read_determinant_list (file, offset, &buffer_size, buffer);
+ if (rc != TREXIO_SUCCESS) {
+ caml_failwith(trexio_string_of_error(rc));
+ }
+
+ result = caml_alloc(buffer_size, 0);
+ size_t icount = 0;
+ for (size_t i=0 ; iback_end < TREXIO_INVALID_BACK_END);
+
+ /* Terminate the back end */
+ switch (file->back_end) {
+
+ case TREXIO_TEXT:
+ rc = trexio_text_flush(file);
+ break;
+
+ case TREXIO_HDF5:
+#ifdef HAVE_HDF5
+ rc = trexio_hdf5_flush(file);
+ break;
+#else
+ return TREXIO_BACK_END_MISSING;
+#endif
+/*
+ case TREXIO_JSON:
+ rc = trexio_json_flush(file);
+ break;
+,*/
+ }
+
+ return rc;
+}
+ #+end_src
+
+*** Fortran
+
+ #+begin_src f90 :tangle prefix_fortran.f90
+interface
+ integer(trexio_exit_code) function trexio_flush (trex_file) bind(C)
+ use, intrinsic :: iso_c_binding
+ import
+ integer(c_int64_t), intent(in), value :: trex_file
+ end function trexio_flush
+end interface
+ #+end_src
+
+*** Python
+
+ #+begin_src python :tangle basic_python.py
+def flush(trexio_file):
+ """Flush buffers into the TREXIO file.
+
+ Parameter is a ~trexio_file~ object that has been created by a call to ~open~ function.
+ """
+
+ rc = pytr.trexio_flush(trexio_file)
+ if rc != TREXIO_SUCCESS:
+ raise Error(rc)
+ #+end_src
+
** File existence
~trexio_inquire~ check whether TREXIO file exists.
@@ -1755,6 +1833,98 @@ trexio_pre_close (trexio_t* file)
considered dimensioning variables and cannot be negative or 0. An attempt to write negative or 0
value will result in ~TREXIO_INVALID_ARG_2~ exit code.
+** Templates for front end has_group functions
+*** Introduction
+
+ This section concerns API calls related to TREXIO groups
+
+ | Function name | Description |
+ |----------------------+-----------------------------------|
+ | ~trexio_has_$group$~ | Check if a group exists in a file |
+
+*** C templates for front end
+
+ The ~C~ templates that correspond to each of the abovementioned
+ functions can be found below. First parameter is the ~TREXIO~ file
+ handle.
+
+**** Function declarations
+
+ #+begin_src c :tangle hrw_group_front.h :exports none
+trexio_exit_code trexio_has_$group$(trexio_t* const file);
+ #+end_src
+
+**** Source code
+
+ #+begin_src c :tangle has_group_front.c
+trexio_exit_code
+trexio_has_$group$ (trexio_t* const file)
+{
+
+ if (file == NULL) return TREXIO_INVALID_ARG_1;
+
+ assert(file->back_end < TREXIO_INVALID_BACK_END);
+
+ switch (file->back_end) {
+
+ case TREXIO_TEXT:
+ return trexio_text_has_$group$(file);
+
+ case TREXIO_HDF5:
+#ifdef HAVE_HDF5
+ return trexio_hdf5_has_$group$(file);
+#else
+ return TREXIO_BACK_END_MISSING;
+#endif
+/*
+ case TREXIO_JSON:
+ return trexio_json_has_$group$(file);
+ break;
+,*/
+ }
+
+ return TREXIO_FAILURE;
+}
+ #+end_src
+
+*** Fortran templates for front end
+
+ The ~Fortran~ templates that provide an access to the ~C~ API calls from Fortran.
+ These templates are based on the use of ~iso_c_binding~. Pointers have to be passed by value.
+
+ #+begin_src f90 :tangle has_group_front_fortran.f90
+interface
+ integer(trexio_exit_code) function trexio_has_$group$ (trex_file) bind(C)
+ use, intrinsic :: iso_c_binding
+ import
+ integer(c_int64_t), intent(in), value :: trex_file
+ end function trexio_has_$group$
+end interface
+ #+end_src
+
+*** Python templates for front end
+
+ #+begin_src python :tangle has_group_front.py
+def has_$group$(trexio_file) -> bool:
+ """Check that $group$ group exists in the TREXIO file.
+
+ Parameter is a ~TREXIO File~ object that has been created by a call to ~open~ function.
+
+ Returns:
+ True if the variable exists, False otherwise
+
+ Raises:
+ - trexio.Error if TREXIO return code ~rc~ is TREXIO_FAILURE and prints the error message using string_of_error.
+ - Exception from some other error (e.g. RuntimeError).
+ """
+
+ rc = pytr.trexio_has_$group$(trexio_file.pytrexio_s)
+ if rc == TREXIO_FAILURE:
+ raise Error(rc)
+
+ return rc == TREXIO_SUCCESS
+ #+end_src
+
** Templates for front end has/read/write a single numerical attribute
*** Introduction
@@ -3924,7 +4094,7 @@ def read_$group_dset$(trexio_file, dim = None) -> list:
"""
$group_dset_dim$ = read_$group_dset_dim$(trexio_file)
-
+
dims_list = [$group_dset_dim_list$]
dim_real = 1
for i in range($group_dset_rank$):
@@ -5189,6 +5359,9 @@ def has_determinant_coefficient(trexio_file) -> bool:
~trexio_to_orbital_list_up_dn~ function does the same but for both up- and down-spin components
of the determinant and returns two list of orbitals each corresponding to a different component.
+ ~trexio_to_bitfield_list~ function converts the list of occupied orbitals (up- or down-spin)
+ into the corresponding ~int64_t~ bitfield representation of the determinant.
+
** C
#+begin_src c :tangle prefix_front.h
@@ -5197,16 +5370,50 @@ trexio_exit_code trexio_mark_safety(trexio_t* const file, const int32_t safety_f
typedef int64_t bitfield_t;
-#define TREXIO_ORBITAL_SHIFT 1
-#define TREXIO_INT_SIZE 64
-#define TREXIO_NORB_PER_INT ( 8*sizeof(bitfield_t) )
-#
+#define TREXIO_ORBITAL_SHIFT 1
+#define TREXIO_INT_SIZE 64
+#define TREXIO_NORB_PER_INT ( 8*sizeof(bitfield_t) )
+#define TREXIO_NORB_PER_INT_SHIFT ( trailz( TREXIO_NORB_PER_INT ) )
+
trexio_exit_code trexio_to_orbital_list (const int32_t N_int, const bitfield_t* d1, int32_t* const list, int32_t* const occupied_num);
trexio_exit_code trexio_to_orbital_list_up_dn (const int32_t N_int, const bitfield_t* d1, int32_t* const list_up, int32_t* const list_dn, int32_t* const occ_num_up, int32_t* const occ_num_dn);
trexio_exit_code trexio_safe_to_orbital_list (const int32_t N_int, const bitfield_t* dset_in, const int64_t dim_in, int32_t* const dset_out, const int64_t dim_out, int32_t* const num);
trexio_exit_code trexio_safe_to_orbital_list_up_dn (const int32_t N_int, const bitfield_t* dset_in, const int64_t dim_in, int32_t* const dset_up_out, const int64_t dim_up_out, int32_t* const dset_dn_out, const int64_t dim_dn_out, int32_t* const num_up, int32_t* const num_dn);
+trexio_exit_code trexio_to_bitfield_list (const int32_t* orb_list, const int32_t occupied_num, bitfield_t* const bit_list, const int32_t N_int);
#+end_src
+
+ #+begin_src c :tangle prefix_front.c
+trexio_exit_code trexio_to_bitfield_list (const int32_t* orb_list,
+ const int32_t occupied_num,
+ bitfield_t* const bit_list,
+ const int32_t N_int)
+{
+ if (orb_list == NULL) return TREXIO_INVALID_ARG_1;
+ if (occupied_num <= 0) return TREXIO_INVALID_ARG_2;
+ if (bit_list == NULL) return TREXIO_INVALID_ARG_3;
+ if (N_int <= 0) return TREXIO_INVALID_ARG_4;
+
+ uint32_t i;
+ uint32_t k;
+ uint32_t iorb;
+
+ for (int32_t j = 0 ; j < N_int ; j++) {
+ bit_list[j] = (bitfield_t) 0;
+ }
+
+ for (int32_t pos = 0 ; pos < occupied_num ; pos++) {
+ iorb = ((uint32_t) (orb_list[pos] + 1)) - TREXIO_ORBITAL_SHIFT;
+ i = (uint32_t) (iorb >> TREXIO_NORB_PER_INT_SHIFT);
+ k = (uint32_t) (iorb & (TREXIO_NORB_PER_INT - 1) );
+ bit_list[i] |= ((bitfield_t) 1) << k;
+ }
+
+ return TREXIO_SUCCESS;
+}
+ #+end_src
+
+
#+begin_src c :tangle prefix_front.c
trexio_exit_code trexio_to_orbital_list(const int32_t N_int,
const bitfield_t* d1,
@@ -5386,10 +5593,24 @@ interface
end interface
#+end_src
+ #+begin_src f90 :tangle prefix_fortran.f90
+interface
+ integer(trexio_exit_code) function trexio_to_bitfield_list_c(list, occupied_num, det_list, N_int) &
+ bind(C, name="trexio_to_bitfield_list")
+ use, intrinsic :: iso_c_binding
+ import
+ integer(c_int32_t), intent(in) :: list(*)
+ integer(c_int32_t), intent(in), value :: occupied_num
+ integer(c_int64_t), intent(inout) :: det_list(*)
+ integer(c_int32_t), intent(in), value :: N_int
+ end function trexio_to_bitfield_list_c
+end interface
+ #+end_src
#+begin_src f90 :tangle prefix_fortran.f90
interface
- integer(trexio_exit_code) function trexio_to_orbital_list_c(N_int, d1, list, occupied_num) bind(C, name="trexio_to_orbital_list")
+ integer(trexio_exit_code) function trexio_to_orbital_list_c(N_int, d1, list, occupied_num) &
+ bind(C, name="trexio_to_orbital_list")
use, intrinsic :: iso_c_binding
import
integer(c_int32_t), intent(in), value :: N_int
@@ -5428,6 +5649,33 @@ def info():
#+end_src
+ #+begin_src python :tangle basic_python.py
+def to_bitfield_list(n_int: int, orbitals: list) -> list:
+ """Convert a list of occupied orbitals into a bitfield determinant.
+
+ Input:
+ ~orbitals~ - list of occupied orbital indices fields (integers)
+ ~n_int~ - number of bitfields per determinant of a given spin
+
+ Returns:
+ ~bitfield_list~: list
+
+ Raises:
+ - Exception from AssertionError if TREXIO return code ~rc~ is different from TREXIO_SUCCESS and prints the error message using trexio_string_of_error.
+ - Exception from some other error (e.g. RuntimeError).
+ """
+
+
+ rc, bitfield_list = pytr.trexio_to_bitfield_list(orbitals, n_int)
+ if rc != TREXIO_SUCCESS:
+ raise Error(rc)
+ if len(bitfield_list) != n_int:
+ raise Exception("Inconsistent size of the bitfield_list.")
+
+ return bitfield_list
+ #+end_src
+
+
#+begin_src python :tangle basic_python.py
def to_orbital_list(n_int: int, determinant: list) -> list:
"""Convert a given determinant into a list of occupied orbitals.
@@ -5454,8 +5702,10 @@ def to_orbital_list(n_int: int, determinant: list) -> list:
raise Exception("Inconsistent size of the orbital_list.")
return orbital_list[0:occ_num]
+ #+end_src
+ #+begin_src python :tangle basic_python.py
def to_orbital_list_up_dn(n_int: int, determinant: list) -> tuple:
"""Convert a given determinant into two lists of occupied orbitals.
@@ -5539,6 +5789,29 @@ contains
by 1 since in Fortran arrays are 1-based and C/Python they are 0-based.
#+begin_src f90 :tangle helper_fortran.f90
+ integer(trexio_exit_code) function trexio_to_bitfield_list(list, occupied_num, det_list, N_int)
+ use, intrinsic :: iso_c_binding
+ implicit none
+
+ integer(c_int32_t), intent(in) :: list(*)
+ integer(c_int32_t), intent(in), value :: occupied_num
+ integer(c_int64_t), intent(out) :: det_list(*)
+ integer(c_int32_t), intent(in), value :: N_int
+ integer(c_int32_t) :: list_0based(occupied_num)
+
+ integer :: i
+ do i = 1,occupied_num
+ list_0based(i) = list(i) - 1
+ enddo
+
+ trexio_to_bitfield_list = trexio_to_bitfield_list_c(list_0based, occupied_num, det_list, N_int)
+ if (trexio_to_bitfield_list /= TREXIO_SUCCESS) then
+ return
+ endif
+
+ end function trexio_to_bitfield_list
+
+
integer(trexio_exit_code) function trexio_to_orbital_list(N_int, d1, list, occupied_num)
use, intrinsic :: iso_c_binding
implicit none
diff --git a/src/templates_hdf5/templator_hdf5.org b/src/templates_hdf5/templator_hdf5.org
index bdfaf61e..989fb67b 100644
--- a/src/templates_hdf5/templator_hdf5.org
+++ b/src/templates_hdf5/templator_hdf5.org
@@ -79,6 +79,21 @@ typedef struct trexio_hdf5_s {
trexio_exit_code trexio_hdf5_init(trexio_t* const file);
trexio_exit_code trexio_hdf5_deinit(trexio_t* const file);
trexio_exit_code trexio_hdf5_inquire(const char* file_name);
+trexio_exit_code trexio_hdf5_flush(trexio_t* const file);
+ #+end_src
+
+ #+begin_src c :tangle basic_hdf5.c
+trexio_exit_code
+trexio_hdf5_flush(trexio_t* const file)
+{
+
+ trexio_hdf5_t* f = (trexio_hdf5_t*) file;
+
+ herr_t rc = H5Fflush(f->file_id, H5F_SCOPE_GLOBAL);
+ if (rc < 0) return TREXIO_FAILURE;
+
+ return TREXIO_SUCCESS;
+}
#+end_src
#+begin_src c :tangle basic_hdf5.c
@@ -179,6 +194,38 @@ trexio_hdf5_deinit (trexio_t* const file)
}
#+end_src
+* Template for HDF5 has a group
+
+ #+begin_src c :tangle hrw_group_hdf5.h :exports none
+trexio_exit_code trexio_hdf5_has_$group$ (trexio_t* const file);
+ #+end_src
+
+
+ #+begin_src c :tangle has_group_hdf5.c
+trexio_exit_code
+trexio_hdf5_has_$group$ (trexio_t* const file)
+{
+
+ if (file == NULL) return TREXIO_INVALID_ARG_1;
+
+ const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
+
+ struct H5G_info_t group_info;
+
+ /* H5Gget_info return info about the HDF5 group as a group_info struct */
+ herr_t status = H5Gget_info(f->$group$_group, &group_info);
+ if (status < 0) return TREXIO_FAILURE;
+
+ /* If nlinks==0 --> the group is empty, i.e. non-existent */
+ if (group_info.nlinks == (hsize_t) 0) {
+ return TREXIO_HAS_NOT;
+ } else {
+ return TREXIO_SUCCESS;
+ }
+
+}
+ #+end_src
+
* Template for HDF5 has/read/write a numerical attribute
#+begin_src c :tangle hrw_attr_num_hdf5.h :exports none
diff --git a/src/templates_text/build.sh b/src/templates_text/build.sh
index b5d73f68..fccd3d24 100644
--- a/src/templates_text/build.sh
+++ b/src/templates_text/build.sh
@@ -13,6 +13,9 @@ cat basic_text.h >> trexio_text.h
cat hrw_determinant_text.h >> trexio_text.h
cat *_determinant_text.c >> trexio_text.c
+cat populated/pop_has_group_text.c >> trexio_text.c
+cat populated/pop_hrw_group_text.h >> trexio_text.h
+
cat populated/pop_free_group_text.c >> trexio_text.c
cat populated/pop_read_group_text.c >> trexio_text.c
cat populated/pop_flush_group_text.c >> trexio_text.c
diff --git a/src/templates_text/templator_text.org b/src/templates_text/templator_text.org
index 7ad22b17..c59e81cd 100644
--- a/src/templates_text/templator_text.org
+++ b/src/templates_text/templator_text.org
@@ -112,6 +112,23 @@ trexio_exit_code trexio_text_inquire(const char* file_name);
trexio_exit_code trexio_text_deinit(trexio_t* const file);
trexio_exit_code trexio_text_lock(trexio_t* const file);
trexio_exit_code trexio_text_unlock(trexio_t* const file);
+trexio_exit_code trexio_text_flush(trexio_t* const file);
+bool trexio_text_file_exists(const char* file_name);
+ #+end_src
+
+ #+begin_src c :tangle basic_text.c
+bool
+trexio_text_file_exists (const char* file_name)
+{
+ /* Check if the file with "file_name" exists */
+ struct stat st;
+
+ int rc = stat(file_name, &st);
+
+ bool file_exists = rc == 0;
+
+ return file_exists;
+}
#+end_src
#+begin_src c :tangle basic_text.c
@@ -127,7 +144,15 @@ trexio_text_inquire (const char* file_name)
if (file_exists) {
- bool is_a_directory = st.st_mode & S_IFDIR;
+ bool is_a_directory = false;
+#ifdef S_IFDIR
+ is_a_directory = st.st_mode & S_IFDIR;
+#elif S_ISDIR
+ is_a_directory = S_ISDIR(s.st_mode);
+#else
+ printf("Some important macros are missing for directory handling.\n");
+ return TREXIO_FAILURE;
+#endif
if (!is_a_directory) return TREXIO_FILE_ERROR;
return TREXIO_SUCCESS;
@@ -268,6 +293,26 @@ trexio_text_deinit (trexio_t* const file)
}
#+end_src
+* Flush function (templated part)
+
+ #+begin_src c :tangle basic_text_group.c
+trexio_exit_code
+trexio_text_flush (trexio_t* const file)
+{
+
+ if (file == NULL) return TREXIO_INVALID_ARG_1;
+
+ trexio_exit_code rc;
+ trexio_text_t* f = (trexio_text_t*) file;
+
+ /* Error handling for this call is added by the generator */
+ rc = trexio_text_flush_$group$(f);
+
+ return TREXIO_SUCCESS;
+
+}
+ #+end_src
+
* Template for text read a group
#+begin_src c :tangle read_group_text.h :exports none
@@ -404,13 +449,14 @@ trexio_text_read_$group$ (trexio_text_t* const file)
/* conventional fcanf with "%s" only return the string before the first space character
* to read string with spaces use "%[^\n]" possible with space before or after, i.e. " %[^\n]"
*/
- rc = fscanf(f, " %1023[^\n]", tmp_$group_dset$);
+ rc = fscanf(f, " %1023[^\n]", buffer);
if (rc != 1) {
trexio_text_free_read_$group$(buffer, f, file, $group$);
return NULL;
}
- size_t tmp_$group_dset$_len = strlen($group$->$group_dset$[i]);
+ size_t tmp_$group_dset$_len = strlen(buffer);
+ strncpy(tmp_$group_dset$, buffer, 32);
tmp_$group_dset$ += tmp_$group_dset$_len + 1;
}
}
@@ -468,14 +514,15 @@ trexio_text_read_$group$ (trexio_text_t* const file)
return NULL;
}
- rc = fscanf(f, " %1023[^\n]", $group$->$group_str$);
+ rc = fscanf(f, " %1023[^\n]", buffer);
if (rc != 1) {
trexio_text_free_read_$group$(buffer, f, file, $group$);
return NULL;
}
+ /* Safer string conversion to avoid buffer overflow in fscanf */
+ strncpy($group$->$group_str$, buffer, $group$->len_$group_str$);
}
-
// END REPEAT GROUP_ATTR_STR
} else {
continue;
@@ -493,6 +540,47 @@ trexio_text_read_$group$ (trexio_text_t* const file)
}
#+end_src
+* Template for text has a group
+
+ #+begin_src c :tangle hrw_group_text.h :exports none
+trexio_exit_code trexio_text_has_$group$(trexio_t* const file);
+ #+end_src
+
+ #+begin_src c :tangle has_group_text.c
+trexio_exit_code
+trexio_text_has_$group$ (trexio_t* const file)
+{
+
+ if (file == NULL) return TREXIO_INVALID_ARG_1;
+
+ /* Flush the group to make sure the group.txt file is created */
+ if (file->mode != 'r') {
+ trexio_exit_code rc = trexio_text_flush_$group$((trexio_text_t*) file);
+ if (rc != TREXIO_SUCCESS) return TREXIO_FAILURE;
+ }
+
+ /* Build the file name */
+ char $group$_full_path[TREXIO_MAX_FILENAME_LENGTH];
+
+ const char* $group$_file_name = "/$group$.txt";
+
+ strncpy ($group$_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH);
+ strncat ($group$_full_path, $group$_file_name,
+ TREXIO_MAX_FILENAME_LENGTH-strlen($group$_file_name));
+
+ if ($group$_full_path[TREXIO_MAX_FILENAME_LENGTH-1] != '\0') return TREXIO_FAILURE;
+
+ bool file_exists;
+ file_exists = trexio_text_file_exists($group$_full_path);
+
+ if (file_exists) {
+ return TREXIO_SUCCESS;
+ } else {
+ return TREXIO_HAS_NOT;
+ }
+}
+ #+end_src
+
* Template for text flush a group
#+begin_src c :tangle flush_group_text.h :exports none
@@ -1063,6 +1151,23 @@ trexio_exit_code trexio_text_write_$group_dset$(trexio_t* const file,
rc = fclose(f_wSize);
if (rc != 0) return TREXIO_FILE_ERROR;
+ const char $group$_file_name[256] = "/$group$.txt";
+
+ memset (file_full_path, 0, TREXIO_MAX_FILENAME_LENGTH);
+ /* Copy directory name in file_full_path */
+ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH);
+ /* Append name of the file with sparse data */
+ strncat (file_full_path, $group$_file_name,
+ TREXIO_MAX_FILENAME_LENGTH-strlen($group$_file_name));
+
+ bool file_exists = trexio_text_file_exists(file_full_path);
+
+ /* Create an empty file for the trexio_text_has_group to work */
+ if (!file_exists) {
+ FILE *fp = fopen(file_full_path, "ab+");
+ fclose(fp);
+ }
+
/* Exit upon success */
return TREXIO_SUCCESS;
}
@@ -1533,6 +1638,24 @@ trexio_exit_code trexio_text_write_determinant_list(trexio_t* const file,
rc = fclose(f);
if (rc != 0) return TREXIO_FILE_ERROR;
+ /* Additional part for the trexio_text_has_group to work */
+ const char det_file_name[256] = "/determinant.txt";
+
+ memset (file_full_path, 0, TREXIO_MAX_FILENAME_LENGTH);
+ /* Copy directory name in file_full_path */
+ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH);
+ /* Append name of the file with sparse data */
+ strncat (file_full_path, det_file_name,
+ TREXIO_MAX_FILENAME_LENGTH-strlen(det_file_name));
+
+ bool file_exists = trexio_text_file_exists(file_full_path);
+
+ /* Create an empty file for the trexio_text_has_group to work */
+ if (!file_exists) {
+ FILE *fp = fopen(file_full_path, "ab+");
+ fclose(fp);
+ }
+
/* Exit upon success */
return TREXIO_SUCCESS;
}
@@ -1602,6 +1725,24 @@ trexio_exit_code trexio_text_write_determinant_coefficient(trexio_t* const file,
rc = fclose(f_wSize);
if (rc != 0) return TREXIO_FILE_ERROR;
+ /* Additional part for the trexio_text_has_group to work */
+ const char det_file_name[256] = "/determinant.txt";
+
+ memset (file_full_path, 0, TREXIO_MAX_FILENAME_LENGTH);
+ /* Copy directory name in file_full_path */
+ strncpy (file_full_path, file->file_name, TREXIO_MAX_FILENAME_LENGTH);
+ /* Append name of the file with sparse data */
+ strncat (file_full_path, det_file_name,
+ TREXIO_MAX_FILENAME_LENGTH-strlen(det_file_name));
+
+ bool file_exists = trexio_text_file_exists(file_full_path);
+
+ /* Create an empty file for the trexio_text_has_group to work */
+ if (!file_exists) {
+ FILE *fp = fopen(file_full_path, "ab+");
+ fclose(fp);
+ }
+
/* Exit upon success */
return TREXIO_SUCCESS;
}
diff --git a/tests/io_all.c b/tests/io_all.c
index e476efd0..cde61cd7 100644
--- a/tests/io_all.c
+++ b/tests/io_all.c
@@ -94,6 +94,10 @@ int test_write(const char* file_name, const back_end_t backend) {
rc = trexio_write_nucleus_coord(file,coord);
assert (rc == TREXIO_SUCCESS);
+ // check the force flushing
+ rc = trexio_flush(file);
+ assert (rc == TREXIO_SUCCESS);
+
rc = trexio_write_nucleus_label(file, label, 32);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_point_group(file, sym, 32);
diff --git a/tests/io_determinant_hdf5.c b/tests/io_determinant_hdf5.c
index c51c2575..c90a2811 100644
--- a/tests/io_determinant_hdf5.c
+++ b/tests/io_determinant_hdf5.c
@@ -307,6 +307,14 @@ static int test_read_determinant (const char* file_name, const back_end_t backen
printf("\n");
*/
+ // check conversion of one orbital list into the bitfield determinant representation
+ int64_t* det_list_check = (int64_t*) calloc(int_num, sizeof(int64_t));
+
+ rc = trexio_to_bitfield_list (orb_list_up, occ_num_up, det_list_check, int_num);
+ assert (rc == TREXIO_SUCCESS);
+ for (int i=0; i size_max)
- offset_file_read = 97;
+ offset_file_read = 97L;
offset_data_read = 1;
int64_t eof_read_size_check = SIZE - offset_file_read; // if offset_file_read=97 => only 3 integrals will be read out of total of 100
@@ -159,11 +167,6 @@ static int test_read_dset_sparse (const char* file_name, const back_end_t backen
assert(chunk_read == eof_read_size_check);
assert(index_read[4*size_r-1] == 0);
assert(index_read[4*offset_data_read] == 4 * (int32_t) (offset_file_read-offset));
- /*
- for(int i=0; i
for line in f_in :
id = check_triggers(line, triggers)
if id == 0:
- # special case for proper error handling when deallocting text groups
+ # special case for proper error handling when deallocating text groups
error_handler = ' if (rc != TREXIO_SUCCESS) return rc;\n'
populated_line = iterative_replace_line(line, '$group$', detailed_all['groups'], add_line=error_handler)
f_out.write(populated_line)
diff --git a/tools/trexio.scm b/tools/trexio.scm
index 5f8deb96..5b3d6eee 100644
--- a/tools/trexio.scm
+++ b/tools/trexio.scm
@@ -1,15 +1,15 @@
-(define-module (gnu packages trexio)
+(define-module (trexio)
#:use-module (guix packages)
#:use-module (gnu packages pkg-config)
#:use-module (gnu packages glib)
#:use-module (gnu packages gcc)
#:use-module (gnu packages autotools)
- #:use-module (gnu packages maths)
+ #:use-module (gnu packages maths) ;; contains hdf5
#:use-module (guix download)
#:use-module (guix build-system gnu)
#:use-module (guix licenses))
-(define-public trexio
+(define-public trexio-2.0
(package
(name "trexio")
(version "2.0")
@@ -20,15 +20,48 @@
".tar.gz"))
(sha256
(base32
+ ;; the hash below is produced by guix download
"1d2cn4w2r9gfid5b9wrq9q290kqdnbjdmvli76s1i5r58kdg5vkf"
))))
(build-system gnu-build-system)
(arguments '(#:configure-flags '("--enable-silent-rules")))
- (inputs `(("hdf5" ,hdf5-1.12) ("gfortran", gfortran)))
- (synopsis "TREX I/O lbrary: trexio package")
- (description "APIs in C and Fortran to exchange wavefunction data.
- Supports HDF5 and TEXT back ends.")
+ (inputs `(("hdf5" ,hdf5) ("gfortran", gfortran)))
+ (synopsis "TREX I/O library")
+ (description "The TREXIO library defines a standard format for storing wave functions, together with
+ an C-compatible API such that it can be easily used in any programming language.")
(home-page "https://trex-coe.github.io/trexio")
(license bsd-3)))
+(define-public trexio-2.1
+ (package/inherit trexio-2.0
+ (version "2.1.0")
+ (source (origin
+ (method url-fetch)
+ (uri (string-append "https://github.com/TREX-CoE/trexio/releases/download/v" version
+ "/trexio-" version
+ ".tar.gz"))
+ (sha256
+ (base32
+ ;; the hash below is produced by guix download
+ "10syfw4mq3wpp9anahmxnm7660bm1ya5xd9l5njai3xr8g4nca13"
+ ))))))
+
+(define-public trexio-2.2
+ (package/inherit trexio-2.0
+ (version "2.2.0")
+ (source (origin
+ (method url-fetch)
+ (uri (string-append "https://github.com/TREX-CoE/trexio/releases/download/v" version
+ "/trexio-" version
+ ".tar.gz"))
+ (sha256
+ (base32
+ ;; the hash below is produced by guix download
+ "1n9n1gbk5hgvg73am991xrv7ap002rz719a3nvh8m8ff9x10qd76"
+ ))))))
+
+(define-public trexio
+ ;; Default version of TREXIO.
+ trexio-2.2)
+
trexio
diff --git a/trex.org b/trex.org
index e9c1a55e..f8080d2e 100644
--- a/trex.org
+++ b/trex.org
@@ -37,6 +37,8 @@ fetched using multiple function calls to perform I/O on buffers.
For more information on how to read/write sparse data structures, see
the [[./examples.html][examples]].
+For determinants, the ~special~ attribute is present in the type. This
+means that the source code is not produced by the generator, but hand-written.
#+begin_src python :tangle trex.json :exports none
{
@@ -68,19 +70,19 @@ the [[./examples.html][examples]].
#+CALL: json(data=metadata, title="metadata")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"metadata": {
- "code_num" : [ "dim", [] ]
- , "code" : [ "str", [ "metadata.code_num" ] ]
- , "author_num" : [ "dim", [] ]
- , "author" : [ "str", [ "metadata.author_num" ] ]
- , "package_version" : [ "str", [] ]
- , "description" : [ "str", [] ]
- , "unsafe" : [ "int", [] ]
+ "code_num" : [ "dim", [] ]
+ , "code" : [ "str", [ "metadata.code_num" ] ]
+ , "author_num" : [ "dim", [] ]
+ , "author" : [ "str", [ "metadata.author_num" ] ]
+ , "package_version" : [ "str", [] ]
+ , "description" : [ "str", [] ]
+ , "unsafe" : [ "int", [] ]
} ,
#+end_src
- :END:
+ :end:
* Electron (electron group)
@@ -195,20 +197,20 @@ If you encounter the aforementioned issue, please report it to our [[https://git
#+CALL: json(data=ecp, title="ecp")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"ecp": {
- "max_ang_mom_plus_1" : [ "int" , [ "nucleus.num" ] ]
- , "z_core" : [ "int" , [ "nucleus.num" ] ]
- , "num" : [ "dim" , [] ]
- , "ang_mom" : [ "int" , [ "ecp.num" ] ]
- , "nucleus_index" : [ "index", [ "ecp.num" ] ]
- , "exponent" : [ "float", [ "ecp.num" ] ]
- , "coefficient" : [ "float", [ "ecp.num" ] ]
- , "power" : [ "int" , [ "ecp.num" ] ]
+ "max_ang_mom_plus_1" : [ "int" , [ "nucleus.num" ] ]
+ , "z_core" : [ "int" , [ "nucleus.num" ] ]
+ , "num" : [ "dim" , [] ]
+ , "ang_mom" : [ "int" , [ "ecp.num" ] ]
+ , "nucleus_index" : [ "index", [ "ecp.num" ] ]
+ , "exponent" : [ "float", [ "ecp.num" ] ]
+ , "coefficient" : [ "float", [ "ecp.num" ] ]
+ , "power" : [ "int" , [ "ecp.num" ] ]
} ,
#+end_src
- :END:
+ :end:
** Example
@@ -322,22 +324,22 @@ power = [
#+CALL: json(data=basis, title="basis")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"basis": {
- "type" : [ "str" , [] ]
- , "prim_num" : [ "dim" , [] ]
- , "shell_num" : [ "dim" , [] ]
- , "nucleus_index" : [ "index", [ "basis.shell_num" ] ]
- , "shell_ang_mom" : [ "int" , [ "basis.shell_num" ] ]
- , "shell_factor" : [ "float", [ "basis.shell_num" ] ]
- , "shell_index" : [ "index", [ "basis.prim_num" ] ]
- , "exponent" : [ "float", [ "basis.prim_num" ] ]
- , "coefficient" : [ "float", [ "basis.prim_num" ] ]
- , "prim_factor" : [ "float", [ "basis.prim_num" ] ]
+ "type" : [ "str" , [] ]
+ , "prim_num" : [ "dim" , [] ]
+ , "shell_num" : [ "dim" , [] ]
+ , "nucleus_index" : [ "index", [ "basis.shell_num" ] ]
+ , "shell_ang_mom" : [ "int" , [ "basis.shell_num" ] ]
+ , "shell_factor" : [ "float", [ "basis.shell_num" ] ]
+ , "shell_index" : [ "index", [ "basis.prim_num" ] ]
+ , "exponent" : [ "float", [ "basis.prim_num" ] ]
+ , "coefficient" : [ "float", [ "basis.prim_num" ] ]
+ , "prim_factor" : [ "float", [ "basis.prim_num" ] ]
} ,
#+end_src
- :END:
+ :end:
** Example
@@ -468,16 +470,16 @@ prim_factor =
#+CALL: json(data=ao, title="ao")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"ao": {
- "cartesian" : [ "int" , [] ]
- , "num" : [ "dim" , [] ]
- , "shell" : [ "index", [ "ao.num" ] ]
- , "normalization" : [ "float", [ "ao.num" ] ]
+ "cartesian" : [ "int" , [] ]
+ , "num" : [ "dim" , [] ]
+ , "shell" : [ "index", [ "ao.num" ] ]
+ , "normalization" : [ "float", [ "ao.num" ] ]
} ,
#+end_src
- :END:
+ :end:
** One-electron integrals (~ao_1e_int~ group)
:PROPERTIES:
@@ -512,22 +514,22 @@ prim_factor =
#+CALL: json(data=ao_1e_int, title="ao_1e_int")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"ao_1e_int": {
- "overlap" : [ "float", [ "ao.num", "ao.num" ] ]
- , "kinetic" : [ "float", [ "ao.num", "ao.num" ] ]
- , "potential_n_e" : [ "float", [ "ao.num", "ao.num" ] ]
- , "ecp" : [ "float", [ "ao.num", "ao.num" ] ]
- , "core_hamiltonian" : [ "float", [ "ao.num", "ao.num" ] ]
- , "overlap_im" : [ "float", [ "ao.num", "ao.num" ] ]
- , "kinetic_im" : [ "float", [ "ao.num", "ao.num" ] ]
- , "potential_n_e_im" : [ "float", [ "ao.num", "ao.num" ] ]
- , "ecp_im" : [ "float", [ "ao.num", "ao.num" ] ]
- , "core_hamiltonian_im" : [ "float", [ "ao.num", "ao.num" ] ]
+ "overlap" : [ "float", [ "ao.num", "ao.num" ] ]
+ , "kinetic" : [ "float", [ "ao.num", "ao.num" ] ]
+ , "potential_n_e" : [ "float", [ "ao.num", "ao.num" ] ]
+ , "ecp" : [ "float", [ "ao.num", "ao.num" ] ]
+ , "core_hamiltonian" : [ "float", [ "ao.num", "ao.num" ] ]
+ , "overlap_im" : [ "float", [ "ao.num", "ao.num" ] ]
+ , "kinetic_im" : [ "float", [ "ao.num", "ao.num" ] ]
+ , "potential_n_e_im" : [ "float", [ "ao.num", "ao.num" ] ]
+ , "ecp_im" : [ "float", [ "ao.num", "ao.num" ] ]
+ , "core_hamiltonian_im" : [ "float", [ "ao.num", "ao.num" ] ]
} ,
#+end_src
- :END:
+ :end:
** Two-electron integrals (~ao_2e_int~ group)
:PROPERTIES:
@@ -579,23 +581,27 @@ prim_factor =
| ~class~ | ~str~ | ~(mo.num)~ | Choose among: Core, Inactive, Active, Virtual, Deleted |
| ~symmetry~ | ~str~ | ~(mo.num)~ | Symmetry in the point group |
| ~occupation~ | ~float~ | ~(mo.num)~ | Occupation number |
+ | ~energy~ | ~float~ | ~(mo.num)~ | For canonical MOs, corresponding eigenvalue |
+ | ~spin~ | ~int~ | ~(mo.num)~ | For UHF wave functions, 0 is $\alpha$ and 1 is $\beta$ |
#+CALL: json(data=mo, title="mo")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"mo": {
- "type" : [ "str" , [] ]
- , "num" : [ "dim" , [] ]
- , "coefficient" : [ "float", [ "mo.num", "ao.num" ] ]
- , "coefficient_im" : [ "float", [ "mo.num", "ao.num" ] ]
- , "class" : [ "str" , [ "mo.num" ] ]
- , "symmetry" : [ "str" , [ "mo.num" ] ]
- , "occupation" : [ "float", [ "mo.num" ] ]
+ "type" : [ "str" , [] ]
+ , "num" : [ "dim" , [] ]
+ , "coefficient" : [ "float", [ "mo.num", "ao.num" ] ]
+ , "coefficient_im" : [ "float", [ "mo.num", "ao.num" ] ]
+ , "class" : [ "str" , [ "mo.num" ] ]
+ , "symmetry" : [ "str" , [ "mo.num" ] ]
+ , "occupation" : [ "float", [ "mo.num" ] ]
+ , "energy" : [ "float", [ "mo.num" ] ]
+ , "spin" : [ "int" , [ "mo.num" ] ]
} ,
#+end_src
- :END:
+ :end:
** One-electron integrals (~mo_1e_int~ group)
@@ -620,22 +626,22 @@ prim_factor =
#+CALL: json(data=mo_1e_int, title="mo_1e_int")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"mo_1e_int": {
- "overlap" : [ "float", [ "mo.num", "mo.num" ] ]
- , "kinetic" : [ "float", [ "mo.num", "mo.num" ] ]
- , "potential_n_e" : [ "float", [ "mo.num", "mo.num" ] ]
- , "ecp" : [ "float", [ "mo.num", "mo.num" ] ]
- , "core_hamiltonian" : [ "float", [ "mo.num", "mo.num" ] ]
- , "overlap_im" : [ "float", [ "mo.num", "mo.num" ] ]
- , "kinetic_im" : [ "float", [ "mo.num", "mo.num" ] ]
- , "potential_n_e_im" : [ "float", [ "mo.num", "mo.num" ] ]
- , "ecp_im" : [ "float", [ "mo.num", "mo.num" ] ]
- , "core_hamiltonian_im" : [ "float", [ "mo.num", "mo.num" ] ]
+ "overlap" : [ "float", [ "mo.num", "mo.num" ] ]
+ , "kinetic" : [ "float", [ "mo.num", "mo.num" ] ]
+ , "potential_n_e" : [ "float", [ "mo.num", "mo.num" ] ]
+ , "ecp" : [ "float", [ "mo.num", "mo.num" ] ]
+ , "core_hamiltonian" : [ "float", [ "mo.num", "mo.num" ] ]
+ , "overlap_im" : [ "float", [ "mo.num", "mo.num" ] ]
+ , "kinetic_im" : [ "float", [ "mo.num", "mo.num" ] ]
+ , "potential_n_e_im" : [ "float", [ "mo.num", "mo.num" ] ]
+ , "ecp_im" : [ "float", [ "mo.num", "mo.num" ] ]
+ , "core_hamiltonian_im" : [ "float", [ "mo.num", "mo.num" ] ]
} ,
#+end_src
- :END:
+ :end:
** Two-electron integrals (~mo_2e_int~ group)
@@ -678,11 +684,16 @@ prim_factor =
in the memory.
\[
- D_I = \alpha_1 \alpha_2 \ldots \alpha_{n\uparrow} \beta_1 \beta_2 \ldots \beta_{n\downarrow}
+ D_I = \alpha_1 \alpha_2 \ldots \alpha_{n_\uparrow} \beta_1 \beta_2 \ldots \beta_{n_\downarrow}
\]
- where $\alpha$ and $\beta$ denote $\uparrow$-spin and $\downarrow$-spin electrons, respectively,
- $n\uparrow$ and $n\downarrow$ correspond to ~electron.up_num~ and ~electron.dn_num~, respectively.
+ where $\alpha$ and $\beta$ denote \uparrow-spin and \downarrow-spin electrons, respectively,
+ $n_\uparrow$ and $n_\downarrow$ correspond to ~electron.up_num~ and ~electron.dn_num~, respectively.
+
+ Note: the ~special~ attribute is present in the types, meaning that the source node is not
+ produced by the code generator.
+
+ An illustration on how to read determinants is presented in the [[./examples.html][examples]].
#+NAME: determinant
| Variable | Type | Dimensions | Description |
@@ -694,15 +705,51 @@ prim_factor =
#+CALL: json(data=determinant, title="determinant")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"determinant": {
- "num" : [ "dim readonly" , [] ]
- , "list" : [ "int special" , [ "determinant.num" ] ]
- , "coefficient" : [ "float special", [ "determinant.num", "state.num" ] ]
+ "num" : [ "dim readonly" , [] ]
+ , "list" : [ "int special" , [ "determinant.num" ] ]
+ , "coefficient" : [ "float special", [ "determinant.num", "state.num" ] ]
} ,
#+end_src
- :END:
+ :end:
+
+* Configuration state functions (csf group)
+
+ The configuration interaction (CI) wave function $\Psi$ can be
+ expanded in the basis of [[https://en.wikipedia.org/wiki/Configuration_state_function][configuration state functions]] (CSFs)
+ $\Psi_I$ as follows
+
+ \[
+ \Psi = \sum_I C_I \psi_I.
+ \]
+
+ Each CSF is a linear combination of Slater determinants. Slater
+ determinants are stored in the =determinant= section. In this group
+ we store the CI coefficients in the basis of CSFs, and the
+ matrix $\langle D_I | \psi_J \rangle$ needed to project the CSFs in
+ the basis of Slater determinants.
+
+ #+NAME: csf
+ | Variable | Type | Dimensions | Description |
+ |-------------------+-----------------+-----------------------------+------------------------------------------------|
+ | ~num~ | ~dim readonly~ | | Number of CSFs |
+ | ~coefficient~ | ~float special~ | ~(state.num,csf.num)~ | Coefficients of the CSFs from the CI expansion |
+ | ~det_coefficient~ | ~float sparse~ | ~(determinant.num,csf.num)~ | Projection on the determinant basis |
+
+ #+CALL: json(data=csf, title="csf")
+
+ #+RESULTS:
+ :results:
+ #+begin_src python :tangle trex.json
+ "csf": {
+ "num" : [ "dim readonly" , [] ]
+ , "coefficient" : [ "float special", [ "csf.num", "state.num" ] ]
+ , "det_coefficient" : [ "float sparse" , [ "csf.num", "determinant.num" ] ]
+ } ,
+ #+end_src
+ :end:
* Excited states (state group)
@@ -720,21 +767,21 @@ prim_factor =
#+CALL: json(data=state, title="state")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"state": {
- "num" : [ "dim", [] ]
- , "label" : [ "str", [ "state.num" ] ]
+ "num" : [ "dim", [] ]
+ , "label" : [ "str", [ "state.num" ] ]
} ,
#+end_src
- :END:
+ :end:
* Reduced density matrices (rdm group)
The reduced density matrices are defined in the basis of molecular
orbitals.
- The $\uparrow$-spin and $\downarrow$-spin components of the one-body
+ The \uparrow-spin and \downarrow-spin components of the one-body
density matrix are given by
\begin{eqnarray*}
\gamma_{ij}^{\uparrow} &=& \langle \Psi | \hat{a}^{\dagger}_{j\alpha}\, \hat{a}_{i\alpha} | \Psi \rangle \\
@@ -812,15 +859,15 @@ prim_factor =
#+CALL: json(data=cell, title="cell")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"cell": {
- "a" : [ "float", [ "3" ] ]
- , "b" : [ "float", [ "3" ] ]
- , "c" : [ "float", [ "3" ] ]
+ "a" : [ "float", [ "3" ] ]
+ , "b" : [ "float", [ "3" ] ]
+ , "c" : [ "float", [ "3" ] ]
} ,
#+end_src
- :END:
+ :end:
* Periodic boundary calculations (pbc group)
@@ -833,14 +880,14 @@ prim_factor =
#+CALL: json(data=pbc, title="pbc")
#+RESULTS:
- :RESULTS:
+ :results:
#+begin_src python :tangle trex.json
"pbc": {
- "periodic" : [ "int" , [] ]
- , "k_point" : [ "float", [ "3" ] ]
+ "periodic" : [ "int" , [] ]
+ , "k_point" : [ "float", [ "3" ] ]
} ,
#+end_src
- :END:
+ :end:
* Quantum Monte Carlo data (qmc group)