1
0
mirror of https://github.com/TREX-CoE/trexio.git synced 2024-12-22 20:35:44 +01:00

Updated formatting

This commit is contained in:
Anthony Scemama 2023-10-18 15:25:57 +02:00
parent c577e61af4
commit 44a03f5551
9 changed files with 349 additions and 287 deletions

View File

@ -5,7 +5,7 @@
[![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)
TREXIO is an open-source file format and library developed for the storage and manipulation of data produced by quantum chemistry calculations. It is designed with the goal of providing a reliable and efficient method of storing and exchanging wave function parameters and matrix elements, making it an important tool for researchers in the field of quantum chemistry. In this work, we present an overview of the TREXIO file format and library. The library consists of a front-end implemented in the C programming language and two different back-ends: a text back-end and a binary back-end utilizing the HDF5 library which enables fast read and write operations. It is compatible with a variety of platforms and has interfaces for the Fortran, Python, and OCaml programming languages. In addition, a suite of tools has been developed to facilitate the use of the TREXIO format and library, including converters for popular quantum chemistry codes and utilities for validating and manipulating data stored in TREXIO files. The simplicity, versatility, and ease of use of TREXIO make it a valuable resource for researchers working with quantum chemistry data.
TREXIO is an open-source file format and library developed for the storage and manipulation of data produced by quantum chemistry calculations. It is designed with the goal of providing a reliable and efficient method of storing and exchanging wave function parameters and matrix elements, making it an important tool for researchers in the field of quantum chemistry. The library consists of a front-end implemented in the C programming language and two different back-ends: a text back-end and a binary back-end utilizing the HDF5 library which enables fast read and write operations. It is compatible with a variety of platforms and has interfaces for the Fortran, Python, OCaml and Rust programming languages.
## Minimal requirements (for users):

View File

@ -2,6 +2,8 @@
name = "trexio"
version = "2.4.0"
edition = "2021"
license = "BSD-3-Clause"
description = "TREXIO is an open-source file format and library developed for the storage and manipulation of data produced by quantum chemistry calculations. It is designed with the goal of providing a reliable and efficient method of storing and exchanging wave function parameters and matrix elements."
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

10
rust/trexio/Makefile Normal file
View File

@ -0,0 +1,10 @@
default: src/generated.rs
cargo build
cargo test
generated.rs: build.py
python3 build.py
test: default
- cargo test -- --show-output

View File

@ -32,6 +32,4 @@ fn main() {
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}

View File

@ -1,37 +1,35 @@
use crate::c;
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Debug, PartialEq)]
pub enum BackEnd {
/// The TREXIO "file" is a directory with text files for each group.
/// A fallback when HDF5 is not available.
Text,
/// The TREXIO "file" is a directory with text files for each group.
/// A fallback when HDF5 is not available.
Text,
/// Should be used for production. The TREXIO file is a single HDF5 file.
Hdf5,
/// Should be used for production. The TREXIO file is a single HDF5 file.
Hdf5,
/// Automatic discovery of the appropriate backend
Auto,
/// Automatic discovery of the appropriate backend
Auto,
}
impl BackEnd {
/// Creation from a C value
pub fn from(b : c::back_end_t) -> Self {
match b {
c::TREXIO_TEXT => Self::Text,
c::TREXIO_HDF5 => Self::Hdf5,
c::TREXIO_AUTO => Self::Auto,
_ => panic!("Invalid backend"),
}
pub fn from(b: c::back_end_t) -> Self {
match b {
c::TREXIO_TEXT => Self::Text,
c::TREXIO_HDF5 => Self::Hdf5,
c::TREXIO_AUTO => Self::Auto,
_ => panic!("Invalid backend"),
}
}
/// Conversion to a C value
pub fn to_c(self) -> c::back_end_t {
match self {
Self::Text => c::TREXIO_TEXT,
Self::Hdf5 => c::TREXIO_HDF5,
Self::Auto => c::TREXIO_AUTO,
Self::Text => c::TREXIO_TEXT,
Self::Hdf5 => c::TREXIO_HDF5,
Self::Auto => c::TREXIO_AUTO,
}
}
}

View File

@ -1,5 +1,4 @@
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Debug, PartialEq)]
pub struct Bitfield {
data: Vec<i64>,
}
@ -8,21 +7,20 @@ use crate::c;
use crate::ExitCode;
impl Bitfield {
/// Creates a new bitfield , using a number of i64 elements consistent
/// with the number of MOs in the TREXIO file.
pub fn from(n_int: usize, orb_list: &[usize]) -> (Self, f64) {
let orb_list: Vec<i32> = orb_list.iter().map(|&x| x as i32).collect();
let occ_num = orb_list.len().try_into().expect("try_into failed in Bitfield::from");
let occ_num = orb_list
.len()
.try_into()
.expect("try_into failed in Bitfield::from");
let orb_list_ptr = orb_list.as_ptr() as *const i32;
let n_int32: i32 = n_int.try_into().expect("try_into failed in Bitfield::from");
let mut b = vec![0i64 ; n_int];
let mut b = vec![0i64; n_int];
let bit_list = b.as_mut_ptr() as *mut c::bitfield_t;
std::mem::forget(b);
let rc = unsafe {
c::trexio_to_bitfield_list(orb_list_ptr, occ_num, bit_list, n_int32)
};
let rc = unsafe { c::trexio_to_bitfield_list(orb_list_ptr, occ_num, bit_list, n_int32) };
let data = unsafe { Vec::from_raw_parts(bit_list, n_int, n_int) };
@ -30,8 +28,8 @@ impl Bitfield {
match ExitCode::from(rc) {
ExitCode::Success => (result, 1.0),
ExitCode::PhaseChange=> (result,-1.0),
x => panic!("TREXIO Error {}", x)
ExitCode::PhaseChange => (result, -1.0),
x => panic!("TREXIO Error {}", x),
}
}
@ -50,14 +48,18 @@ impl Bitfield {
/// Returns the alpha part
pub fn alpha(&self) -> Bitfield {
let n_int = self.data.len()/2;
Bitfield { data: (&self.data[0..n_int]).to_vec() }
let n_int = self.data.len() / 2;
Bitfield {
data: (&self.data[0..n_int]).to_vec(),
}
}
/// Returns the beta part
pub fn beta(&self) -> Bitfield {
let n_int = self.data.len()/2;
Bitfield { data: (&self.data[n_int..2*n_int]).to_vec() }
let n_int = self.data.len() / 2;
Bitfield {
data: (&self.data[n_int..2 * n_int]).to_vec(),
}
}
/// Converts to a format usable in the C library
@ -76,20 +78,23 @@ impl Bitfield {
/// Converts the bitfield into a list of orbital indices (0-based)
pub fn to_orbital_list(&self) -> Vec<usize> {
let n_int : i32 = self.data.len().try_into().expect("try_into failed in to_orbital_list");
let n_int: i32 = self
.data
.len()
.try_into()
.expect("try_into failed in to_orbital_list");
let d1 = self.as_ptr();
let cap = self.data.len() * 64;
let mut list = vec![ 0i32 ; cap ];
let mut list = vec![0i32; cap];
let list_c = list.as_mut_ptr() as *mut i32;
std::mem::forget(list);
let mut occ_num : i32 = 0;
let mut occ_num: i32 = 0;
let rc = unsafe { c::trexio_to_orbital_list(n_int, d1, list_c, &mut occ_num) };
match ExitCode::from(rc) {
ExitCode::Success => (),
x => panic!("TREXIO Error {}", x)
x => panic!("TREXIO Error {}", x),
};
let occ_num = occ_num as usize;
@ -97,7 +102,7 @@ impl Bitfield {
let mut result: Vec<usize> = Vec::with_capacity(occ_num);
for i in list.iter() {
result.push( *i as usize );
result.push(*i as usize);
}
result
}
@ -109,24 +114,34 @@ impl Bitfield {
/// Converts the determinant into a list of orbital indices (0-based)
pub fn to_orbital_list_up_dn(&self) -> (Vec<usize>, Vec<usize>) {
let n_int : i32 = (self.data.len()/2).try_into().expect("try_into failed in to_orbital_list");
let n_int: i32 = (self.data.len() / 2)
.try_into()
.expect("try_into failed in to_orbital_list");
let d1 = self.as_ptr();
let cap = self.data.len()/2 * 64;
let mut b = vec![ 0i32 ; cap ];
let cap = self.data.len() / 2 * 64;
let mut b = vec![0i32; cap];
let list_up_c = b.as_mut_ptr() as *mut i32;
std::mem::forget(b);
let mut b = vec![ 0i32 ; cap ];
let mut b = vec![0i32; cap];
let list_dn_c = b.as_mut_ptr() as *mut i32;
std::mem::forget(b);
let mut occ_num_up : i32 = 0;
let mut occ_num_dn : i32 = 0;
let mut occ_num_up: i32 = 0;
let mut occ_num_dn: i32 = 0;
let rc = unsafe { c::trexio_to_orbital_list_up_dn(n_int, d1, list_up_c, list_dn_c, &mut occ_num_up, &mut occ_num_dn) };
let rc = unsafe {
c::trexio_to_orbital_list_up_dn(
n_int,
d1,
list_up_c,
list_dn_c,
&mut occ_num_up,
&mut occ_num_dn,
)
};
match ExitCode::from(rc) {
ExitCode::Success => (),
x => panic!("TREXIO Error {}", x)
x => panic!("TREXIO Error {}", x),
};
let occ_num_up = occ_num_up as usize;
@ -136,26 +151,23 @@ impl Bitfield {
let mut result_up: Vec<usize> = Vec::with_capacity(occ_num_up);
for i in list_up.iter() {
result_up.push( *i as usize );
result_up.push(*i as usize);
}
let mut result_dn: Vec<usize> = Vec::with_capacity(occ_num_dn);
for i in list_dn.iter() {
result_dn.push( *i as usize );
result_dn.push(*i as usize);
}
(result_up, result_dn)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn creation_from_list() {
let list0 = vec![0, 1, 2, 3, 4];
let list1 = vec![0, 1, 2, 4, 3];
let list2 = vec![0, 1, 4, 2, 3];
@ -173,16 +185,15 @@ mod tests {
let list = alpha2.to_orbital_list();
assert_eq!(list, list0);
assert_eq!(phase2, phase0);
}
#[test]
fn creation_alpha_beta() {
let (alpha, _) = Bitfield::from(2, &[0, 1, 2, 3, 4]);
let (beta , _) = Bitfield::from(2, &[0, 1, 2, 4, 5]);
let (beta, _) = Bitfield::from(2, &[0, 1, 2, 4, 5]);
let det = Bitfield::from_alpha_beta(&alpha, &beta);
let list = det.to_orbital_list();
assert_eq!(list, [0,1,2,3,4,128,129,130,132,133]);
assert_eq!(list, [0, 1, 2, 3, 4, 128, 129, 130, 132, 133]);
assert_eq!(det.alpha(), alpha);
assert_eq!(det.beta(), beta);
}
@ -191,7 +202,7 @@ mod tests {
#[should_panic]
fn creation_alpha_beta_with_different_nint() {
let (alpha, _) = Bitfield::from(1, &[0, 1, 2, 3, 4]);
let (beta , _) = Bitfield::from(2, &[0, 1, 2, 4, 5]);
let (beta, _) = Bitfield::from(2, &[0, 1, 2, 4, 5]);
let _ = Bitfield::from_alpha_beta(&alpha, &beta);
}
}

View File

@ -1,7 +1,6 @@
use crate::c;
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Debug, PartialEq)]
pub enum ExitCode {
/// Unknown failure
Failure,
@ -98,115 +97,113 @@ pub enum ExitCode {
/// The function succeeded with a change of sign
PhaseChange,
}
impl ExitCode {
/// Creation from a C value
pub fn from(rc : c::trexio_exit_code) -> Self {
pub fn from(rc: c::trexio_exit_code) -> Self {
match rc {
c::TREXIO_FAILURE => Self::Failure,
c::TREXIO_SUCCESS => Self::Success,
c::TREXIO_INVALID_ARG_1 => Self::InvalidArg(1),
c::TREXIO_INVALID_ARG_2 => Self::InvalidArg(2),
c::TREXIO_INVALID_ARG_3 => Self::InvalidArg(3),
c::TREXIO_INVALID_ARG_4 => Self::InvalidArg(4),
c::TREXIO_INVALID_ARG_5 => Self::InvalidArg(5),
c::TREXIO_END => Self::End,
c::TREXIO_READONLY => Self::ReadOnly,
c::TREXIO_ERRNO => Self::Errno,
c::TREXIO_INVALID_ID => Self::InvalidId,
c::TREXIO_ALLOCATION_FAILED => Self::AllocationFailed,
c::TREXIO_HAS_NOT => Self::HasNot,
c::TREXIO_INVALID_NUM => Self::InvalidNum,
c::TREXIO_ATTR_ALREADY_EXISTS => Self::AttrAlreadyExists,
c::TREXIO_DSET_ALREADY_EXISTS => Self::DsetAlreadyExists,
c::TREXIO_OPEN_ERROR => Self::OpenError,
c::TREXIO_LOCK_ERROR => Self::LockError,
c::TREXIO_UNLOCK_ERROR => Self::UnlockError,
c::TREXIO_FILE_ERROR => Self::FileError,
c::TREXIO_GROUP_READ_ERROR => Self::GroupReadError,
c::TREXIO_GROUP_WRITE_ERROR => Self::GroupWriteError,
c::TREXIO_ELEM_READ_ERROR => Self::ElemReadError,
c::TREXIO_ELEM_WRITE_ERROR => Self::ElemWriteError,
c::TREXIO_UNSAFE_ARRAY_DIM => Self::UnsafeArrayDim,
c::TREXIO_ATTR_MISSING => Self::AttrMissing,
c::TREXIO_DSET_MISSING => Self::DsetMissing,
c::TREXIO_BACK_END_MISSING => Self::BackEndMissing,
c::TREXIO_INVALID_ARG_6 => Self::InvalidArg(6),
c::TREXIO_INVALID_ARG_7 => Self::InvalidArg(7),
c::TREXIO_INVALID_ARG_8 => Self::InvalidArg(8),
c::TREXIO_INVALID_STR_LEN => Self::InvalidStrLen,
c::TREXIO_INT_SIZE_OVERFLOW => Self::IntSizeOverflow,
c::TREXIO_SAFE_MODE => Self::SafeMode,
c::TREXIO_INVALID_ELECTRON_NUM => Self::InvalidElectronNum,
c::TREXIO_INVALID_DETERMINANT_NUM => Self::InvalidDeterminantNum,
c::TREXIO_INVALID_STATE => Self::InvalidState,
c::TREXIO_VERSION_PARSING_ISSUE => Self::VersionParsingIssue,
c::TREXIO_PHASE_CHANGE => Self::PhaseChange,
_ => panic!("Unknown exit code"),
c::TREXIO_FAILURE => Self::Failure,
c::TREXIO_SUCCESS => Self::Success,
c::TREXIO_INVALID_ARG_1 => Self::InvalidArg(1),
c::TREXIO_INVALID_ARG_2 => Self::InvalidArg(2),
c::TREXIO_INVALID_ARG_3 => Self::InvalidArg(3),
c::TREXIO_INVALID_ARG_4 => Self::InvalidArg(4),
c::TREXIO_INVALID_ARG_5 => Self::InvalidArg(5),
c::TREXIO_END => Self::End,
c::TREXIO_READONLY => Self::ReadOnly,
c::TREXIO_ERRNO => Self::Errno,
c::TREXIO_INVALID_ID => Self::InvalidId,
c::TREXIO_ALLOCATION_FAILED => Self::AllocationFailed,
c::TREXIO_HAS_NOT => Self::HasNot,
c::TREXIO_INVALID_NUM => Self::InvalidNum,
c::TREXIO_ATTR_ALREADY_EXISTS => Self::AttrAlreadyExists,
c::TREXIO_DSET_ALREADY_EXISTS => Self::DsetAlreadyExists,
c::TREXIO_OPEN_ERROR => Self::OpenError,
c::TREXIO_LOCK_ERROR => Self::LockError,
c::TREXIO_UNLOCK_ERROR => Self::UnlockError,
c::TREXIO_FILE_ERROR => Self::FileError,
c::TREXIO_GROUP_READ_ERROR => Self::GroupReadError,
c::TREXIO_GROUP_WRITE_ERROR => Self::GroupWriteError,
c::TREXIO_ELEM_READ_ERROR => Self::ElemReadError,
c::TREXIO_ELEM_WRITE_ERROR => Self::ElemWriteError,
c::TREXIO_UNSAFE_ARRAY_DIM => Self::UnsafeArrayDim,
c::TREXIO_ATTR_MISSING => Self::AttrMissing,
c::TREXIO_DSET_MISSING => Self::DsetMissing,
c::TREXIO_BACK_END_MISSING => Self::BackEndMissing,
c::TREXIO_INVALID_ARG_6 => Self::InvalidArg(6),
c::TREXIO_INVALID_ARG_7 => Self::InvalidArg(7),
c::TREXIO_INVALID_ARG_8 => Self::InvalidArg(8),
c::TREXIO_INVALID_STR_LEN => Self::InvalidStrLen,
c::TREXIO_INT_SIZE_OVERFLOW => Self::IntSizeOverflow,
c::TREXIO_SAFE_MODE => Self::SafeMode,
c::TREXIO_INVALID_ELECTRON_NUM => Self::InvalidElectronNum,
c::TREXIO_INVALID_DETERMINANT_NUM => Self::InvalidDeterminantNum,
c::TREXIO_INVALID_STATE => Self::InvalidState,
c::TREXIO_VERSION_PARSING_ISSUE => Self::VersionParsingIssue,
c::TREXIO_PHASE_CHANGE => Self::PhaseChange,
_ => panic!("Unknown exit code"),
}
}
/// Conversion to a C value
pub fn to_c(&self) -> c::trexio_exit_code {
pub fn to_c(&self) -> c::trexio_exit_code {
match self {
Self::Failure => c::TREXIO_FAILURE,
Self::Success => c::TREXIO_SUCCESS,
Self::InvalidArg(1) => c::TREXIO_INVALID_ARG_1,
Self::InvalidArg(2) => c::TREXIO_INVALID_ARG_2,
Self::InvalidArg(3) => c::TREXIO_INVALID_ARG_3,
Self::InvalidArg(4) => c::TREXIO_INVALID_ARG_4,
Self::InvalidArg(5) => c::TREXIO_INVALID_ARG_5,
Self::End => c::TREXIO_END,
Self::ReadOnly => c::TREXIO_READONLY,
Self::Errno => c::TREXIO_ERRNO,
Self::InvalidId => c::TREXIO_INVALID_ID,
Self::AllocationFailed => c::TREXIO_ALLOCATION_FAILED,
Self::HasNot => c::TREXIO_HAS_NOT,
Self::InvalidNum => c::TREXIO_INVALID_NUM,
Self::AttrAlreadyExists => c::TREXIO_ATTR_ALREADY_EXISTS,
Self::DsetAlreadyExists => c::TREXIO_DSET_ALREADY_EXISTS,
Self::OpenError => c::TREXIO_OPEN_ERROR,
Self::LockError => c::TREXIO_LOCK_ERROR,
Self::UnlockError => c::TREXIO_UNLOCK_ERROR,
Self::FileError => c::TREXIO_FILE_ERROR,
Self::GroupReadError => c::TREXIO_GROUP_READ_ERROR,
Self::GroupWriteError => c::TREXIO_GROUP_WRITE_ERROR,
Self::ElemReadError => c::TREXIO_ELEM_READ_ERROR,
Self::ElemWriteError => c::TREXIO_ELEM_WRITE_ERROR,
Self::UnsafeArrayDim => c::TREXIO_UNSAFE_ARRAY_DIM,
Self::AttrMissing => c::TREXIO_ATTR_MISSING,
Self::DsetMissing => c::TREXIO_DSET_MISSING,
Self::BackEndMissing => c::TREXIO_BACK_END_MISSING,
Self::InvalidArg(6) => c::TREXIO_INVALID_ARG_6,
Self::InvalidArg(7) => c::TREXIO_INVALID_ARG_7,
Self::InvalidArg(8) => c::TREXIO_INVALID_ARG_8,
Self::InvalidStrLen => c::TREXIO_INVALID_STR_LEN,
Self::IntSizeOverflow => c::TREXIO_INT_SIZE_OVERFLOW,
Self::SafeMode => c::TREXIO_SAFE_MODE,
Self::InvalidElectronNum => c::TREXIO_INVALID_ELECTRON_NUM,
Self::InvalidDeterminantNum => c::TREXIO_INVALID_DETERMINANT_NUM,
Self::InvalidState => c::TREXIO_INVALID_STATE,
Self::VersionParsingIssue => c::TREXIO_VERSION_PARSING_ISSUE,
Self::PhaseChange => c::TREXIO_PHASE_CHANGE,
_ => panic!("Unknown exit code"),
Self::Failure => c::TREXIO_FAILURE,
Self::Success => c::TREXIO_SUCCESS,
Self::InvalidArg(1) => c::TREXIO_INVALID_ARG_1,
Self::InvalidArg(2) => c::TREXIO_INVALID_ARG_2,
Self::InvalidArg(3) => c::TREXIO_INVALID_ARG_3,
Self::InvalidArg(4) => c::TREXIO_INVALID_ARG_4,
Self::InvalidArg(5) => c::TREXIO_INVALID_ARG_5,
Self::End => c::TREXIO_END,
Self::ReadOnly => c::TREXIO_READONLY,
Self::Errno => c::TREXIO_ERRNO,
Self::InvalidId => c::TREXIO_INVALID_ID,
Self::AllocationFailed => c::TREXIO_ALLOCATION_FAILED,
Self::HasNot => c::TREXIO_HAS_NOT,
Self::InvalidNum => c::TREXIO_INVALID_NUM,
Self::AttrAlreadyExists => c::TREXIO_ATTR_ALREADY_EXISTS,
Self::DsetAlreadyExists => c::TREXIO_DSET_ALREADY_EXISTS,
Self::OpenError => c::TREXIO_OPEN_ERROR,
Self::LockError => c::TREXIO_LOCK_ERROR,
Self::UnlockError => c::TREXIO_UNLOCK_ERROR,
Self::FileError => c::TREXIO_FILE_ERROR,
Self::GroupReadError => c::TREXIO_GROUP_READ_ERROR,
Self::GroupWriteError => c::TREXIO_GROUP_WRITE_ERROR,
Self::ElemReadError => c::TREXIO_ELEM_READ_ERROR,
Self::ElemWriteError => c::TREXIO_ELEM_WRITE_ERROR,
Self::UnsafeArrayDim => c::TREXIO_UNSAFE_ARRAY_DIM,
Self::AttrMissing => c::TREXIO_ATTR_MISSING,
Self::DsetMissing => c::TREXIO_DSET_MISSING,
Self::BackEndMissing => c::TREXIO_BACK_END_MISSING,
Self::InvalidArg(6) => c::TREXIO_INVALID_ARG_6,
Self::InvalidArg(7) => c::TREXIO_INVALID_ARG_7,
Self::InvalidArg(8) => c::TREXIO_INVALID_ARG_8,
Self::InvalidStrLen => c::TREXIO_INVALID_STR_LEN,
Self::IntSizeOverflow => c::TREXIO_INT_SIZE_OVERFLOW,
Self::SafeMode => c::TREXIO_SAFE_MODE,
Self::InvalidElectronNum => c::TREXIO_INVALID_ELECTRON_NUM,
Self::InvalidDeterminantNum => c::TREXIO_INVALID_DETERMINANT_NUM,
Self::InvalidState => c::TREXIO_INVALID_STATE,
Self::VersionParsingIssue => c::TREXIO_VERSION_PARSING_ISSUE,
Self::PhaseChange => c::TREXIO_PHASE_CHANGE,
_ => panic!("Unknown exit code"),
}
}
pub fn to_str(&self) -> Result<&'static str, Utf8Error> {
let c_error = self.to_c();
let c_buf: *const c_char = unsafe { c::trexio_string_of_error( c_error ) };
let c_buf: *const c_char = unsafe { c::trexio_string_of_error(c_error) };
let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) };
c_str.to_str()
}
}
use std::fmt;
use std::error::Error;
use std::ffi::CStr;
use std::ffi::c_char;
use std::ffi::CStr;
use std::fmt;
use std::str::Utf8Error;
impl fmt::Display for ExitCode {

View File

@ -1,12 +1,12 @@
/// TREXIO is an open-source file format and library developed for the storage and manipulation of
/// data produced by quantum chemistry calculations. It was designed with the goal of providing a
/// reliable and efficient method of storing and exchanging wave function parameters and matrix
/// elements.
///
/// For comprehensive documentation, consult: [TREXIO Documentation](https://trex-coe.github.io/trexio/)
///
/// The C library source code is available on GitHub: [TREXIO GitHub Repository](https://github.com/trex-coe/trexio)
///
//! TREXIO is an open-source file format and library developed for the storage and manipulation of
//! data produced by quantum chemistry calculations. It was designed with the goal of providing a
//! reliable and efficient method of storing and exchanging wave function parameters and matrix
//! elements.
//!
//! For comprehensive documentation, consult: [TREXIO Documentation](https://trex-coe.github.io/trexio/)
//!
//! The C library source code is available on GitHub: [TREXIO GitHub Repository](https://github.com/trex-coe/trexio)
//!
use ::std::os::raw::c_char;
@ -16,6 +16,7 @@ mod c;
/// These error codes are mapped to those defined in the original C TREXIO library.
pub mod exit_code;
pub use exit_code::ExitCode;
use exit_code::ExitCode::InvalidArg;
/// Enum representing the different backends that TREXIO can employ for data storage.
pub mod back_end;
@ -26,14 +27,15 @@ pub mod bitfield;
pub use bitfield::Bitfield;
/// A constant string representing the package version of the linked C TREXIO library.
pub const PACKAGE_VERSION : &str = unsafe { std::str::from_utf8_unchecked(c::TREXIO_PACKAGE_VERSION) };
pub const PACKAGE_VERSION: &str =
unsafe { std::str::from_utf8_unchecked(c::TREXIO_PACKAGE_VERSION) };
/// Utility function to convert Rust results into TREXIO exit codes.
fn rc_return<T>(result: T, rc : c::trexio_exit_code) -> Result<T,ExitCode> {
fn rc_return<T>(result: T, rc: c::trexio_exit_code) -> Result<T, ExitCode> {
let rc = ExitCode::from(rc);
match rc {
ExitCode::Success => Ok(result),
x => Err(x)
x => Err(x),
}
}
@ -42,22 +44,18 @@ fn string_to_c(s: &str) -> std::ffi::CString {
std::ffi::CString::new(s).unwrap()
}
/// Function to print out diagnostic information about the linked C TREXIO library.
pub fn info() -> Result<(),ExitCode> {
pub fn info() -> Result<(), ExitCode> {
let rc = unsafe { c::trexio_info() };
rc_return((), rc)
}
/// Type representing a TREXIO file. Wraps a pointer to the underlying C structure.
pub struct File {
ptr: *mut c::trexio_t,
}
impl File {
/// Opens a TREXIO file. Returns a `File` instance that can be used for subsequent I/O operations.
///
/// # Parameters
@ -88,7 +86,6 @@ impl File {
rc_return((), rc)
}
/// Inquires if a file with the specified name exists.
///
/// # Parameters
@ -107,7 +104,7 @@ impl File {
match ExitCode::from(rc) {
ExitCode::Failure => Ok(false),
ExitCode::Success => Ok(true),
x => Err(x),
x => Err(x),
}
}
@ -157,11 +154,9 @@ impl File {
/// otherwise returns `Err(ExitCode)`.
pub fn get_int64_num(&self) -> Result<usize, ExitCode> {
let mut num = 0i32;
let rc = unsafe {
c::trexio_get_int64_num(self.ptr, &mut num)
};
let num:usize = num.try_into().expect("try_into failed in get_int64_num");
rc_return(num, rc)
let rc = unsafe { c::trexio_get_int64_num(self.ptr, &mut num) };
let num: usize = num.try_into().expect("try_into failed in get_int64_num");
rc_return(num, rc)
}
/// Writes a vector of determinants, represented as [Bitfield] objects.
@ -175,27 +170,36 @@ impl File {
///
/// * `Result<(), ExitCode>` - Returns `Ok(())` if the operation is successful,
/// otherwise returns `Err(ExitCode)`.
pub fn write_determinant_list(&self, offset: usize, determinants: &[Bitfield]) -> Result<(), ExitCode> {
pub fn write_determinant_list(
&self,
offset: usize,
determinants: &[Bitfield],
) -> Result<(), ExitCode> {
let n_int = self.get_int64_num()?;
match determinants.len() {
0 => return Ok(()),
_ => if determinants[0].as_vec().len() != 2*n_int {
return Err(exit_code::Invalid_Arg(3))
_ => {
if determinants[0].as_vec().len() != 2 * n_int {
return Err(InvalidArg(3));
}
}
};
let offset: i64 = offset.try_into().expect("try_into failed in write_determinant_list");
let buffer_size: i64 = determinants.len().try_into().expect("try_into failed in write_determinant_list");
let offset: i64 = offset
.try_into()
.expect("try_into failed in write_determinant_list");
let buffer_size: i64 = determinants
.len()
.try_into()
.expect("try_into failed in write_determinant_list");
let mut one_d_array: Vec<i64> = Vec::with_capacity(determinants.len() * n_int);
for det in determinants.iter() {
for i in det.as_vec().iter() {
one_d_array.push(i.clone());
}
for i in det.as_vec().iter() {
one_d_array.push(i.clone());
}
}
let dset: *const i64 = one_d_array.as_ptr() as *const i64;
let rc = unsafe {
c::trexio_write_determinant_list(self.ptr, offset, buffer_size, dset)
};
rc_return((), rc)
let rc = unsafe { c::trexio_write_determinant_list(self.ptr, offset, buffer_size, dset) };
rc_return((), rc)
}
/// Reads a vector of determinants, represented as [Bitfield] objects.
@ -207,34 +211,50 @@ impl File {
///
/// # Returns
///
/// * `Result<Vec<Bitfield>, ExitCode>` - Returns the read determinants as `Ok(Vec<Bitfield>)`
/// * `Result<Vec<Bitfield>, ExitCode>` - Returns the read determinants as `Ok(Vec<Bitfield>)`
/// if the operation is successful, otherwise returns `Err(ExitCode)`.
pub fn read_determinant_list(&self, offset: usize, buffer_size: usize) -> Result<Vec<Bitfield>, ExitCode> {
pub fn read_determinant_list(
&self,
offset: usize,
buffer_size: usize,
) -> Result<Vec<Bitfield>, ExitCode> {
let n_int = self.get_int64_num()?;
let mut one_d_array: Vec<i64> = Vec::with_capacity(buffer_size * 2* n_int);
let mut one_d_array: Vec<i64> = Vec::with_capacity(buffer_size * 2 * n_int);
let one_d_array_ptr = one_d_array.as_ptr() as *mut i64;
let rc = unsafe {
let offset: i64 = offset.try_into().expect("try_into failed in read_determinant_list (offset)");
let mut buffer_size_read: i64 = buffer_size.try_into().expect("try_into failed in read_determinant_list (buffer_size)");
let rc = c::trexio_read_determinant_list(self.ptr, offset, &mut buffer_size_read, one_d_array_ptr);
let buffer_size_read: usize = buffer_size_read.try_into().expect("try_into failed in read_determinant_list (buffer_size)");
one_d_array.set_len(n_int*2usize*buffer_size_read);
let offset: i64 = offset
.try_into()
.expect("try_into failed in read_determinant_list (offset)");
let mut buffer_size_read: i64 = buffer_size
.try_into()
.expect("try_into failed in read_determinant_list (buffer_size)");
let rc = c::trexio_read_determinant_list(
self.ptr,
offset,
&mut buffer_size_read,
one_d_array_ptr,
);
let buffer_size_read: usize = buffer_size_read
.try_into()
.expect("try_into failed in read_determinant_list (buffer_size)");
one_d_array.set_len(n_int * 2usize * buffer_size_read);
match ExitCode::from(rc) {
ExitCode::End => ExitCode::to_c(&ExitCode::Success),
ExitCode::Success => { assert_eq!(buffer_size_read, buffer_size); rc }
_ => rc
ExitCode::End => ExitCode::to_c(&ExitCode::Success),
ExitCode::Success => {
assert_eq!(buffer_size_read, buffer_size);
rc
}
_ => rc,
}
};
let result: Vec::<Bitfield> = one_d_array.chunks(2*n_int)
.collect::<Vec<_>>()
.iter()
.map(|x| (Bitfield::from_vec(&x)))
.collect::<Vec<_>>();
rc_return(result, rc)
let result: Vec<Bitfield> = one_d_array
.chunks(2 * n_int)
.collect::<Vec<_>>()
.iter()
.map(|x| (Bitfield::from_vec(&x)))
.collect::<Vec<_>>();
rc_return(result, rc)
}
}
include!("generated.rs");

View File

@ -1,49 +1,49 @@
use trexio::back_end::BackEnd;
use trexio::bitfield::Bitfield;
fn write(file_name: &str, back_end: BackEnd) -> Result<(), trexio::ExitCode> {
// Prepare data to be written
let nucleus_num = 12;
let state_id = 2;
let charge = vec![6., 6., 6., 6., 6., 6., 1., 1., 1., 1., 1., 1.0f64];
let coord = vec![ [ 0.00000000f64, 1.39250319 , 0.00 ],
[ -1.20594314, 0.69625160 , 0.00 ],
[ -1.20594314, -0.69625160 , 0.00 ],
[ 0.00000000, -1.39250319 , 0.00 ],
[ 1.20594314, -0.69625160 , 0.00 ],
[ 1.20594314, 0.69625160 , 0.00 ],
[ -2.14171677, 1.23652075 , 0.00 ],
[ -2.14171677, -1.23652075 , 0.00 ],
[ 0.00000000, -2.47304151 , 0.00 ],
[ 2.14171677, -1.23652075 , 0.00 ],
[ 2.14171677, 1.23652075 , 0.00 ],
[ 0.00000000, 2.47304151 , 0.00 ]];
let coord = vec![
[0.00000000f64, 1.39250319, 0.00],
[-1.20594314, 0.69625160, 0.00],
[-1.20594314, -0.69625160, 0.00],
[0.00000000, -1.39250319, 0.00],
[1.20594314, -0.69625160, 0.00],
[1.20594314, 0.69625160, 0.00],
[-2.14171677, 1.23652075, 0.00],
[-2.14171677, -1.23652075, 0.00],
[0.00000000, -2.47304151, 0.00],
[2.14171677, -1.23652075, 0.00],
[2.14171677, 1.23652075, 0.00],
[0.00000000, 2.47304151, 0.00],
];
let flat_coord = coord.into_iter().flatten().collect::<Vec<f64>>();
let mo_num = 150;
let ao_num = 1000;
let basis_shell_num = 24;
let basis_nucleus_index: Vec<usize> = (0..24).collect();
let label = vec![ "C", "Na", "C", "C 66", "C",
"C", "H 99", "Ru", "H", "H", "H", "H" ];
let label = vec![
"C", "Na", "C", "C 66", "C", "C", "H 99", "Ru", "H", "H", "H", "H",
];
let sym_str = "B3U with some comments";
println!("Write {}", file_name);
assert!( ! trexio::File::inquire(file_name)? );
assert!(!trexio::File::inquire(file_name)?);
let trex_file = trexio::File::open(file_name, 'w', back_end)?;
assert!( ! trex_file.has_nucleus()? );
assert!( ! trex_file.has_nucleus_num()? );
assert!( ! trex_file.has_nucleus_charge()? );
assert!( ! trex_file.has_ao_2e_int()? );
assert!( ! trex_file.has_ao_2e_int_eri()? );
assert!( ! trex_file.has_determinant_list()? );
assert!(!trex_file.has_nucleus()?);
assert!(!trex_file.has_nucleus_num()?);
assert!(!trex_file.has_nucleus_charge()?);
assert!(!trex_file.has_ao_2e_int()?);
assert!(!trex_file.has_ao_2e_int_eri()?);
assert!(!trex_file.has_determinant_list()?);
trex_file.write_nucleus_num(nucleus_num)?;
trex_file.write_nucleus_charge(&charge)?;
@ -54,84 +54,80 @@ fn write(file_name: &str, back_end: BackEnd) -> Result<(), trexio::ExitCode> {
trex_file.write_basis_nucleus_index(&basis_nucleus_index)?;
trex_file.write_state_id(state_id)?;
if ! trex_file.has_ao_num()? {
if !trex_file.has_ao_num()? {
trex_file.write_ao_num(ao_num)?;
}
if ! trex_file.has_mo_num()? {
if !trex_file.has_mo_num()? {
trex_file.write_mo_num(mo_num)?;
}
let mut energy = Vec::with_capacity(mo_num);
for i in 0..mo_num {
let e: f64 = i as f64 -100.0f64;
let e: f64 = i as f64 - 100.0f64;
energy.push(e);
}
trex_file.write_mo_energy(&energy)?;
let mut spin = vec![0 ; mo_num];
for i in mo_num/2..mo_num {
let mut spin = vec![0; mo_num];
for i in mo_num / 2..mo_num {
spin[i] = 1;
}
trex_file.write_mo_spin(&spin)?;
// Integrals
let nmax = 100;
let mut ao_2e_int_eri = Vec::<(usize,usize,usize,usize,f64)>::with_capacity(nmax);
let mut ao_2e_int_eri = Vec::<(usize, usize, usize, usize, f64)>::with_capacity(nmax);
let n_buffers = 5;
let bufsize = nmax/n_buffers;
let bufsize = nmax / n_buffers;
for i in 0..100 {
// Quadruplet of indices + value
let data = (4*i, 4*i+1, 4*i+2, 4*i+3, 3.14 + (i as f64));
let data = (4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3, 3.14 + (i as f64));
ao_2e_int_eri.push(data);
}
let mut offset = 0;
for _ in 0..n_buffers {
trex_file.write_ao_2e_int_eri(offset, &ao_2e_int_eri[offset..offset+bufsize])?;
trex_file.write_ao_2e_int_eri(offset, &ao_2e_int_eri[offset..offset + bufsize])?;
offset += bufsize;
}
// Determinants
let det_num = 50;
let mut det_list = Vec::with_capacity(det_num);
for i in 0..det_num {
let mut d = [0i64 ; 6 ];
let mut d = [0i64; 6];
for j in 0..6 {
d[j] = 6*(i as i64)+(j as i64);
d[j] = 6 * (i as i64) + (j as i64);
}
det_list.push( Bitfield::from_vec(&d) );
det_list.push(Bitfield::from_vec(&d));
}
let n_buffers = 5;
let bufsize = 50/n_buffers;
let bufsize = 50 / n_buffers;
let mut offset = 0;
for _ in 0..n_buffers {
trex_file.write_determinant_list(offset, &det_list[offset..offset+bufsize])?;
trex_file.write_determinant_list(offset, &det_list[offset..offset + bufsize])?;
offset += bufsize;
}
trex_file.close()
}
fn read(file_name: &str, back_end: BackEnd) -> Result<(), trexio::ExitCode> {
println!("Read {}", file_name);
assert!( trexio::File::inquire(file_name)? );
assert!(trexio::File::inquire(file_name)?);
let trex_file = trexio::File::open(file_name, 'r', back_end)?;
assert!( trex_file.has_nucleus()? );
assert!( trex_file.has_nucleus_num()? );
assert!( trex_file.has_nucleus_charge()? );
assert!( trex_file.has_ao_2e_int()? );
assert!( trex_file.has_ao_2e_int_eri()? );
assert!( trex_file.has_determinant_list()? );
assert!(trex_file.has_nucleus()?);
assert!(trex_file.has_nucleus_num()?);
assert!(trex_file.has_nucleus_charge()?);
assert!(trex_file.has_ao_2e_int()?);
assert!(trex_file.has_ao_2e_int_eri()?);
assert!(trex_file.has_determinant_list()?);
let nucleus_num = trex_file.read_nucleus_num()?;
assert_eq!(nucleus_num, 12);
@ -140,31 +136,65 @@ fn read(file_name: &str, back_end: BackEnd) -> Result<(), trexio::ExitCode> {
assert_eq!(sym_str, "B3U with some comments");
let charge = trex_file.read_nucleus_charge()?;
assert_eq!(charge, vec![6., 6., 6., 6., 6., 6., 1., 1., 1., 1., 1., 1.0f64]);
assert_eq!(
charge,
vec![6., 6., 6., 6., 6., 6., 1., 1., 1., 1., 1., 1.0f64]
);
let coord = trex_file.read_nucleus_coord()?;
assert_eq!(coord, vec![ 0.00000000f64, 1.39250319 , 0.00,
-1.20594314, 0.69625160 , 0.00,
-1.20594314, -0.69625160 , 0.00,
0.00000000, -1.39250319 , 0.00,
1.20594314, -0.69625160 , 0.00,
1.20594314, 0.69625160 , 0.00,
-2.14171677, 1.23652075 , 0.00,
-2.14171677, -1.23652075 , 0.00,
0.00000000, -2.47304151 , 0.00,
2.14171677, -1.23652075 , 0.00,
2.14171677, 1.23652075 , 0.00,
0.00000000, 2.47304151 , 0.00 ]);
assert_eq!(
coord,
vec![
0.00000000f64,
1.39250319,
0.00,
-1.20594314,
0.69625160,
0.00,
-1.20594314,
-0.69625160,
0.00,
0.00000000,
-1.39250319,
0.00,
1.20594314,
-0.69625160,
0.00,
1.20594314,
0.69625160,
0.00,
-2.14171677,
1.23652075,
0.00,
-2.14171677,
-1.23652075,
0.00,
0.00000000,
-2.47304151,
0.00,
2.14171677,
-1.23652075,
0.00,
2.14171677,
1.23652075,
0.00,
0.00000000,
2.47304151,
0.00
]
);
let label = trex_file.read_nucleus_label(6)?;
assert_eq!(label, vec![ "C", "Na", "C", "C 66", "C",
"C", "H 99", "Ru", "H", "H", "H", "H" ]);
assert_eq!(
label,
vec!["C", "Na", "C", "C 66", "C", "C", "H 99", "Ru", "H", "H", "H", "H"]
);
let basis_shell_num = trex_file.read_basis_shell_num()?;
assert_eq!(basis_shell_num, 24);
let basis_nucleus_index = trex_file.read_basis_nucleus_index()?;
let ref_val : Vec<usize> = (0..24).collect();
let ref_val: Vec<usize> = (0..24).collect();
assert_eq!(basis_nucleus_index, ref_val);
let state_id = trex_file.read_state_id()?;
@ -178,14 +208,14 @@ fn read(file_name: &str, back_end: BackEnd) -> Result<(), trexio::ExitCode> {
let mut energy_ref = Vec::with_capacity(mo_num);
for i in 0..mo_num {
let e: f64 = i as f64 -100.0f64;
let e: f64 = i as f64 - 100.0f64;
energy_ref.push(e);
}
let energy = trex_file.read_mo_energy()?;
assert_eq!(energy, energy_ref);
let mut spin_ref = vec![0 ; mo_num];
for i in mo_num/2..mo_num {
let mut spin_ref = vec![0; mo_num];
for i in mo_num / 2..mo_num {
spin_ref[i] = 1;
}
let spin = trex_file.read_mo_spin()?;
@ -193,19 +223,19 @@ fn read(file_name: &str, back_end: BackEnd) -> Result<(), trexio::ExitCode> {
// Integrals
let nmax = 100;
let mut ao_2e_int_eri_ref = Vec::<(usize,usize,usize,usize,f64)>::with_capacity(nmax);
let mut ao_2e_int_eri_ref = Vec::<(usize, usize, usize, usize, f64)>::with_capacity(nmax);
let n_buffers = 8;
let bufsize = nmax/n_buffers+10;
let bufsize = nmax / n_buffers + 10;
for i in 0..100 {
// Quadruplet of indices + value
let data = (4*i, 4*i+1, 4*i+2, 4*i+3, 3.14 + (i as f64));
let data = (4 * i, 4 * i + 1, 4 * i + 2, 4 * i + 3, 3.14 + (i as f64));
ao_2e_int_eri_ref.push(data);
}
let mut offset = 0;
let mut ao_2e_int_eri = Vec::<(usize,usize,usize,usize,f64)>::with_capacity(nmax);
let mut ao_2e_int_eri = Vec::<(usize, usize, usize, usize, f64)>::with_capacity(nmax);
for _ in 0..n_buffers {
let buffer = trex_file.read_ao_2e_int_eri(offset, bufsize)?;
offset += buffer.len();
@ -213,22 +243,21 @@ fn read(file_name: &str, back_end: BackEnd) -> Result<(), trexio::ExitCode> {
}
assert_eq!(ao_2e_int_eri_ref, ao_2e_int_eri);
// Determinants
let det_num = trex_file.read_determinant_num()?;
assert_eq!(det_num, 50);
let mut det_list_ref = Vec::with_capacity(det_num);
for i in 0..det_num {
let mut d = [0i64 ; 6 ];
let mut d = [0i64; 6];
for j in 0..6 {
d[j] = 6*(i as i64)+(j as i64);
d[j] = 6 * (i as i64) + (j as i64);
}
det_list_ref.push( Bitfield::from_vec(&d) );
det_list_ref.push(Bitfield::from_vec(&d));
}
let n_buffers = 8;
let bufsize = det_num/n_buffers + 20;
let bufsize = det_num / n_buffers + 20;
let mut offset = 0;
let mut det_list: Vec<Bitfield> = Vec::with_capacity(det_num);
for _ in 0..n_buffers {
@ -239,7 +268,6 @@ fn read(file_name: &str, back_end: BackEnd) -> Result<(), trexio::ExitCode> {
assert_eq!(det_list_ref, det_list);
trex_file.close()
}
#[test]
@ -247,7 +275,6 @@ pub fn info() {
let _ = trexio::info();
}
use std::fs;
#[test]
@ -263,4 +290,3 @@ pub fn hdf5_backend() {
let _ = read("tmp/test_write.hdf5", trexio::BackEnd::Hdf5).unwrap();
fs::remove_file("tmp/test_write.hdf5").unwrap()
}