1
0
mirror of https://github.com/TREX-CoE/trexio.git synced 2024-07-22 18:57:39 +02:00

Merge pull request #91 from TREX-CoE/add-determinants

Add I/O for determinants
This commit is contained in:
Anthony Scemama 2022-04-23 19:24:49 +02:00 committed by GitHub
commit 5ca632af2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 3181 additions and 390 deletions

View File

@ -112,6 +112,7 @@ TESTS_C = \
tests/io_dset_float_text \
tests/io_dset_int_text \
tests/io_dset_sparse_text \
tests/io_determinant_text \
tests/io_safe_dset_float_text \
tests/io_str_text \
tests/io_dset_str_text \
@ -127,6 +128,7 @@ TESTS_C += \
tests/io_dset_float_hdf5 \
tests/io_dset_int_hdf5 \
tests/io_dset_sparse_hdf5 \
tests/io_determinant_hdf5 \
tests/io_safe_dset_float_hdf5 \
tests/io_str_hdf5 \
tests/io_dset_str_hdf5 \

View File

@ -9,7 +9,7 @@ from setuptools import setup, Extension
def parse_setuppy_commands():
"""Check the commands and respond appropriately.
At the moment it is adapted to ignore checks for numpy, plgconfig, HDF5 flags
At the moment it is adapted to ignore checks for numpy, pkgconfig, HDF5 flags
when building the distribution tarball with sdist option.
"""
args = sys.argv[1:]
@ -93,7 +93,11 @@ pytrexio_module = Extension('pytrexio._pytrexio',
sources = [os.path.join(srcpath, code) for code in c_files],
include_dirs = [h5_cflags, srcpath, numpy_includedir],
libraries = ['hdf5', 'hdf5_hl'],
extra_compile_args = ['-Wno-discarded-qualifiers'],
extra_compile_args = [
'-Wno-discarded-qualifiers',
'-Wno-unused-variable',
'-Wno-unused-but-set-variable'
],
extra_link_args = [h5_ldflags]
)

View File

@ -118,17 +118,40 @@ coords = [
trexio.write_nucleus_coord(test_file, coords)
# write mo_num (needed later to write sparse mo_2e_int_eri integrals)
trexio.write_mo_num(test_file, 600)
# write ao_num (needed later to write sparse ao_2e_int_eri integrals)
trexio.write_ao_num(test_file, 600)
# write sparse data in the file
num_integrals = 100
indices = [i for i in range(num_integrals*4)]
values = [(3.14 + float(i)) for i in range(num_integrals)]
trexio.write_mo_2e_int_eri(test_file, 0, num_integrals, indices, values)
trexio.write_ao_2e_int_eri(test_file, 0, num_integrals, indices, values)
# write mo_num (needed later to write determinants)
mo_num = 150
trexio.write_mo_num(test_file, mo_num)
int_num = 2*int((mo_num-1)/64+1)
# write determinants in the file
num_dets = 50
offset = 0
dets = [i for i in range(num_dets*int_num)]
coeffs = [(3.14 + float(i)) for i in range(num_dets)]
coeffs_s2 = [(6.28 + float(i)) for i in range(num_dets)]
trexio.write_determinant_list(test_file, offset, num_dets, dets)
trexio.write_determinant_coefficient(test_file, offset, num_dets, coeffs)
test_file.set_state(2)
trexio.write_determinant_coefficient(test_file, offset, num_dets, coeffs_s2)
test_file.set_state(0)
# manually check the consistency between coefficient_size and number of determinants
assert trexio.read_determinant_coefficient_size(test_file) == trexio.read_determinant_num(test_file)
# write nucleus_point_group in the file
point_group = 'B3U'
@ -210,7 +233,9 @@ assert trexio.has_nucleus_charge(test_file2)
assert trexio.has_nucleus_coord(test_file2)
assert trexio.has_nucleus_label(test_file2)
assert trexio.has_nucleus_point_group(test_file2)
assert trexio.has_mo_2e_int_eri(test_file2)
assert trexio.has_ao_2e_int_eri(test_file2)
assert trexio.has_determinant_list(test_file2)
assert trexio.has_determinant_coefficient(test_file2)
# read nucleus_num from file
rnum = trexio.read_nucleus_num(test_file2)
@ -254,14 +279,14 @@ np.testing.assert_array_almost_equal(rcoords_np, np.array(coords).reshape(nucleu
#rcoords_reshaped_2 = trexio.read_nucleus_coord(test_file2, doReshape=False)
# read number of integrals already present in the file
assert trexio.has_mo_2e_int_eri(test_file2)
assert trexio.read_mo_2e_int_eri_size(test_file2)==num_integrals
assert trexio.has_ao_2e_int_eri(test_file2)
assert trexio.read_ao_2e_int_eri_size(test_file2)==num_integrals
# read sparse arrays on mo_2e_int_eri integrals
# read sparse arrays on ao_2e_int_eri integrals
buf_size = 60
offset_file = 0
# read full buf_size (i.e. the one that does not reach EOF)
indices_sparse_np, value_sparse_np, read_buf_size, eof = trexio.read_mo_2e_int_eri(test_file2, offset_file, buf_size)
indices_sparse_np, value_sparse_np, read_buf_size, eof = trexio.read_ao_2e_int_eri(test_file2, offset_file, buf_size)
print(f'First complete sparse read size: {read_buf_size}')
#print(indices_sparse_np)
assert not eof
@ -271,7 +296,7 @@ assert indices_sparse_np[read_buf_size-1][3]==read_buf_size*4-1
offset_file += buf_size
# read incomplete buf_size (i.e. the one that does reach EOF)
indices_sparse_np, value_sparse_np, read_buf_size, eof2 = trexio.read_mo_2e_int_eri(test_file2, offset_file, buf_size)
indices_sparse_np, value_sparse_np, read_buf_size, eof2 = trexio.read_ao_2e_int_eri(test_file2, offset_file, buf_size)
print(f'Second incomplete sparse read size: {read_buf_size}')
#print(indices_sparse_np)
assert eof2
@ -279,6 +304,39 @@ assert read_buf_size==(num_integrals - buf_size)
assert indices_sparse_np[0][0]==offset_file*4
assert indices_sparse_np[read_buf_size-1][3]==(offset_file+read_buf_size)*4-1
# read number of determinants already present in the file
assert trexio.has_determinant_list(test_file2)
assert trexio.read_determinant_num(test_file2)==num_dets
# read determinants (list of ints and float coefficients)
buf_size = 20
offset_file = 0
# read full buf_size (i.e. the one that does not reach EOF)
dets_np, read_buf_size, eof = trexio.read_determinant_list(test_file2, offset_file, buf_size)
print(f'First complete read of determinant list: {read_buf_size}')
#print(indices_sparse_np)
assert not eof
assert read_buf_size==buf_size
assert dets_np[0][0]==0
assert dets_np[read_buf_size-1][int_num-1]==read_buf_size*int_num-1
coefficients_np, read_buf_size, eof = trexio.read_determinant_coefficient(test_file2, offset_file, buf_size)
print(f'First complete read of determinant coefficients: {read_buf_size}')
#print(indices_sparse_np)
assert not eof
assert read_buf_size==buf_size
# convert one determinant into a list of orbitals
dets_tmp = dets_np[read_buf_size-1][:]
#print(dets_tmp)
# divide by 2 because in this test int_num is the total number of integers (i.e. up-spin + down_spin)
orb_list_up, orb_list_dn = trexio.to_orbital_list_up_dn(int(int_num/2), dets_tmp)
assert(orb_list_up[0] == 2)
assert(orb_list_dn[0] == 1)
#print(orb_list_up)
#print(orb_list_dn)
# read array of nuclear labels
rlabels_2d = trexio.read_nucleus_label(test_file2, dim=nucleus_num)

View File

@ -36,6 +36,10 @@
/* Return num variables as part of the output tuple */
%apply int *OUTPUT { int32_t* const num};
%apply int *OUTPUT { int64_t* const num};
%apply int *OUTPUT { int32_t* const num_up};
%apply int *OUTPUT { int32_t* const num_dn};
%apply int *OUTPUT { int64_t* const num_up};
%apply int *OUTPUT { int64_t* const num_dn};
%apply float *OUTPUT { float* const num};
%apply float *OUTPUT { double* const num};
/* Return TREXIO exit code from trexio_open as part of the output tuple */
@ -75,6 +79,7 @@ import_array();
%numpy_typemaps(float, NPY_FLOAT, int64_t)
%numpy_typemaps(int32_t, NPY_INT32, int64_t)
%numpy_typemaps(int64_t, NPY_INT64, int64_t)
%numpy_typemaps(bitfield_t, NPY_INT64, int64_t)
/* Enable write|read_safe functions to convert numpy arrays from/to double arrays */
%apply (double* ARGOUT_ARRAY1, int64_t DIM1) {(double* const dset_out, const int64_t dim_out)};
%apply (double* IN_ARRAY1, int64_t DIM1) {(const double* dset_in, const int64_t dim_in)};
@ -93,6 +98,12 @@ import_array();
%apply (double* ARGOUT_ARRAY1, int64_t DIM1) {(double* const value_sparse_read, const int64_t size_value_read)};
%apply (int32_t* ARGOUT_ARRAY1, int64_t DIM1) {(int32_t* const index_sparse_read, const int64_t size_index_read)};
/* Enable write|read_safe functions to convert numpy arrays from orbital list arrays */
%apply (int32_t* ARGOUT_ARRAY1, int64_t DIM1) {(int32_t* const dset_up_out, const int64_t dim_up_out)};
%apply (int32_t* ARGOUT_ARRAY1, int64_t DIM1) {(int32_t* const dset_dn_out, const int64_t dim_dn_out)};
%apply (int64_t* ARGOUT_ARRAY1, int64_t DIM1) {(int64_t* const dset_up_out, const int64_t dim_up_out)};
%apply (int64_t* ARGOUT_ARRAY1, int64_t DIM1) {(int64_t* const dset_dn_out, const int64_t dim_dn_out)};
%apply (bitfield_t* IN_ARRAY1, int64_t DIM1) {(const bitfield_t* dset_in, const int64_t dim_in)};
/* This tells SWIG to treat char ** dset_in pattern as a special case
Enables access to trexio_[...]_write_dset_str set of functions directly, i.e.

View File

@ -38,9 +38,14 @@ echo "" >> trexio_f.f90
# c front end
cat populated/pop_*.c >> trexio.c
cat populated/pop_*.h >> trexio.h
# add determinant part
cat hrw_determinant_front.h >> trexio.h
cat *_determinant_front.c >> trexio.c
# fortran front end
cat populated/pop_*.f90 >> trexio_f.f90
# add determinant part
cat *_determinant_front_fortran.f90 >> trexio_f.f90
# add helper functions
cat helper_fortran.f90 >> trexio_f.f90
cat populated/pop_*.fh_90 >> trexio_f.f90
@ -48,6 +53,7 @@ cat populated/pop_*.fh_90 >> trexio_f.f90
# python front end
cat basic_python.py >> trexio.py
cat populated/pop_*.py >> trexio.py
cat *_determinant_front.py >> trexio.py
# suffixes
cat suffix_s_front.h >> trexio_s.h

File diff suppressed because it is too large Load Diff

View File

@ -14,5 +14,8 @@ cat populated/pop_delete_group_hdf5.c >> trexio_hdf5.c
cat populated/pop_hrw_*.h >> trexio_hdf5.h
cat populated/pop_delete_group_hdf5.h >> trexio_hdf5.h
cat hrw_determinant_hdf5.h >> trexio_hdf5.h
cat *_determinant_hdf5.c >> trexio_hdf5.c
cat helpers_hdf5.c >> trexio_hdf5.c
cat suffix_hdf5.h >> trexio_hdf5.h

View File

@ -265,6 +265,7 @@ trexio_hdf5_has_$group_num$ (trexio_t* const file)
if (file == NULL) return TREXIO_INVALID_ARG_1;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
if (f->$group$_group == (hsize_t) 0) return TREXIO_HAS_NOT;
htri_t status = H5Aexists(f->$group$_group, $GROUP_NUM$_NAME);
/* H5Aexists returns positive value if attribute exists, 0 if does not, negative if error */
@ -399,6 +400,7 @@ trexio_hdf5_has_$group_dset$ (trexio_t* const file)
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
if (f->$group$_group == (hsize_t) 0) return TREXIO_HAS_NOT;
herr_t status = H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME);
/* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */
@ -441,7 +443,7 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file,
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
hid_t index_dtype;
const void* index_p;
void* index_p = NULL;
uint64_t size_ranked = (uint64_t) size * $group_dset_rank$;
/* Determine the optimal type for storing indices depending on the size_max (usually mo_num or ao_num) */
if (size_max < UINT8_MAX) {
@ -461,7 +463,7 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file,
index_p = index;
index_dtype = H5T_NATIVE_UINT16;
} else {
index_p = (const int32_t*) index_sparse;
index_p = (int32_t*) index_sparse;
index_dtype = H5T_NATIVE_INT32;
}
@ -546,11 +548,11 @@ trexio_hdf5_read_$group_dset$ (trexio_t* const file,
trexio_exit_code rc_read;
// attempt to read indices
rc_read = trexio_hdf5_open_read_dset_sparse(f->$group$_group, dset_index_name, offset_i, count_i, NULL, is_index, index_read);
rc_read = trexio_hdf5_open_read_dset_sparse(f->$group$_group, dset_index_name, $group_dset_rank$, offset_i, count_i, NULL, is_index, index_read);
if (rc_read != TREXIO_SUCCESS && rc_read != TREXIO_END) return rc_read;
// attempt to read values
// when EOF is encountered - the count_v[0] is modified and contains the number of elements being read
rc_read = trexio_hdf5_open_read_dset_sparse(f->$group$_group, dset_value_name, offset_v, count_v, eof_read_size, is_value, value_read);
rc_read = trexio_hdf5_open_read_dset_sparse(f->$group$_group, dset_value_name, 1, offset_v, count_v, eof_read_size, is_value, value_read);
if (rc_read != TREXIO_SUCCESS && rc_read != TREXIO_END) return rc_read;
return rc_read;
@ -564,6 +566,7 @@ trexio_hdf5_read_$group_dset$_size (trexio_t* const file, int64_t* const size_ma
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (size_max == NULL) return TREXIO_INVALID_ARG_2;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
@ -600,6 +603,7 @@ trexio_hdf5_has_$group_dset$ (trexio_t* const file)
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
if (f->$group$_group == (hsize_t) 0) return TREXIO_HAS_NOT;
herr_t status = H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME "_values");
/* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */
@ -798,6 +802,7 @@ trexio_hdf5_has_$group_dset$ (trexio_t* const file)
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
if (f->$group$_group == (hsize_t) 0) return TREXIO_HAS_NOT;
herr_t status = H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME);
/* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */
@ -927,6 +932,7 @@ trexio_hdf5_has_$group_str$ (trexio_t* const file)
if (file == NULL) return TREXIO_INVALID_ARG_1;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
if (f->$group$_group == (hsize_t) 0) return TREXIO_HAS_NOT;
htri_t status = H5Aexists(f->$group$_group, $GROUP_STR$_NAME);
/* H5Aexists returns positive value if attribute exists, 0 if does not, negative if error */
@ -977,6 +983,262 @@ trexio_hdf5_delete_$group$ (trexio_t* const file)
}
#+end_src
* Source code for the determinant part
Each array is stored in a separate HDF5 dataset due to the fact that determinant I/O has to be decoupled.
Chunks are used to read/write the data to prevent memory overflow. Chunks have a given ~int64_t dims[0]*dims[1]~.
Size specifies the number of data items (e.g. determinants) to process.
#+begin_src c :tangle hrw_determinant_hdf5.h :exports none
trexio_exit_code trexio_hdf5_has_determinant_list(trexio_t* const file);
trexio_exit_code trexio_hdf5_read_determinant_list(trexio_t* const file, const int64_t offset_file, const uint32_t rank, const uint64_t* dims, int64_t* const eof_read_size, int64_t* const list);
trexio_exit_code trexio_hdf5_write_determinant_list(trexio_t* const file, const int64_t offset_file, const uint32_t rank, const uint64_t* dims, const int64_t* list);
trexio_exit_code trexio_hdf5_has_determinant_coefficient(trexio_t* const file);
trexio_exit_code trexio_hdf5_read_determinant_coefficient(trexio_t* const file, const int64_t offset_file, const uint32_t rank, const uint64_t* dims, int64_t* const eof_read_size, double* const coeff);
trexio_exit_code trexio_hdf5_write_determinant_coefficient(trexio_t* const file, const int64_t offset_file, const uint32_t rank, const uint64_t* dims, const double* coeff);
trexio_exit_code trexio_hdf5_read_determinant_coefficient_size(trexio_t* const file, int64_t* const size_max);
#+end_src
#+begin_src c :tangle read_determinant_hdf5.c
trexio_exit_code trexio_hdf5_read_determinant_list(trexio_t* const file,
const int64_t offset_file,
const uint32_t rank,
const uint64_t* dims,
int64_t* const eof_read_size,
int64_t* const list)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5;
if (list == NULL) return TREXIO_INVALID_ARG_6;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
char dset_det_name[256] = "determinant_list";
hsize_t offset[1] = {(hsize_t) offset_file * dims[1]};
hsize_t count[1] = {(hsize_t) dims[0] * dims[1]};
/* Attempt to read determinants (if EOF -> eof_read_size is modified with the number of elements read and return code is TREXIO_END)
0 argument below is requires to skip internal treatment specific to sparse indices (i.e. their de-compression).*/
return trexio_hdf5_open_read_dset_sparse(f->determinant_group, dset_det_name, (uint32_t) dims[1], offset, count, eof_read_size, 0, list);
}
trexio_exit_code trexio_hdf5_read_determinant_coefficient(trexio_t* const file,
const int64_t offset_file,
const uint32_t rank,
const uint64_t* dims,
int64_t* const eof_read_size,
double* const coeff)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5;
if (coeff == NULL) return TREXIO_INVALID_ARG_6;
char dset_coeff_name[128];
memset(dset_coeff_name, 0, sizeof(dset_coeff_name));
const int32_t trexio_state = file->state;
if (trexio_state != 0) {
sprintf(dset_coeff_name, "determinant_coefficient_state_%" PRId32, trexio_state);
} else {
strncpy(dset_coeff_name, "determinant_coefficient", 24);
}
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
hsize_t offset[1] = {(hsize_t) offset_file};
hsize_t count[1] = {(hsize_t) dims[0]};
/* Attempt to read determinants (if EOF -> eof_read_size is modified with the number of elements read and return code is TREXIO_END)
0 argument below is requires to skip internal treatment specific to sparse indices (i.e. their de-compression).*/
return trexio_hdf5_open_read_dset_sparse(f->determinant_group, dset_coeff_name, 1, offset, count, eof_read_size, 0, coeff);
}
#+end_src
#+begin_src c :tangle write_determinant_hdf5.c
trexio_exit_code trexio_hdf5_write_determinant_list(trexio_t* const file,
const int64_t offset_file,
const uint32_t rank,
const uint64_t* dims,
const int64_t* list)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (list == NULL) return TREXIO_INVALID_ARG_5;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
hid_t det_dtype = H5T_NATIVE_INT64;
uint64_t size_ranked = dims[1]*dims[0];
/* Arrays of chunk dims that will be used for chunking the dataset */
const hsize_t chunk_dims[1] = {size_ranked};
/* Indices and values are stored as 2 independent datasets in the HDF5 file */
char dset_det_name[256] = "determinant_list";
trexio_exit_code rc_write = TREXIO_FAILURE;
/* NOTE: chunk size is set upon creation of the HDF5 dataset and cannot be changed ! */
if ( H5LTfind_dataset(f->determinant_group, dset_det_name) != 1 ) {
/* If the file does not exist -> create it and write */
/* Create chunked dataset with det_dtype datatype and write indices into it */
rc_write = trexio_hdf5_create_write_dset_sparse(f->determinant_group, dset_det_name, det_dtype, chunk_dims, list);
if (rc_write != TREXIO_SUCCESS) return rc_write;
} else {
/* If the file exists -> open it and write */
hsize_t offset_data[1] = {(hsize_t) offset_file * dims[1]};
/* Create chunked dataset with det_dtype datatype and write indices into it */
rc_write = trexio_hdf5_open_write_dset_sparse(f->determinant_group, dset_det_name, det_dtype, chunk_dims, offset_data, list);
if (rc_write != TREXIO_SUCCESS) return rc_write;
}
return TREXIO_SUCCESS;
}
trexio_exit_code trexio_hdf5_write_determinant_coefficient(trexio_t* const file,
const int64_t offset_file,
const uint32_t rank,
const uint64_t* dims,
const double* coeff)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (coeff == NULL) return TREXIO_INVALID_ARG_5;
char dset_coeff_name[128];
memset(dset_coeff_name, 0, sizeof(dset_coeff_name));
const int32_t trexio_state = file->state;
if (trexio_state != 0) {
sprintf(dset_coeff_name, "determinant_coefficient_state_%" PRId32, trexio_state);
} else {
strncpy(dset_coeff_name, "determinant_coefficient", 24);
}
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
hid_t det_dtype = H5T_NATIVE_DOUBLE;
/* Arrays of chunk dims that will be used for chunking the dataset */
const hsize_t chunk_dims[1] = {(hsize_t) dims[0]};
trexio_exit_code rc_write = TREXIO_FAILURE;
/* NOTE: chunk size is set upon creation of the HDF5 dataset and cannot be changed ! */
if ( H5LTfind_dataset(f->determinant_group, dset_coeff_name) != 1 ) {
/* If the file does not exist -> create it and write */
/* Create chunked dataset with det_dtype datatype and write indices into it */
rc_write = trexio_hdf5_create_write_dset_sparse(f->determinant_group, dset_coeff_name, det_dtype, chunk_dims, coeff);
if (rc_write != TREXIO_SUCCESS) return rc_write;
} else {
/* If the file exists -> open it and write */
hsize_t offset_data[1] = {(hsize_t) offset_file};
/* Create chunked dataset with det_dtype datatype and write indices into it */
rc_write = trexio_hdf5_open_write_dset_sparse(f->determinant_group, dset_coeff_name, det_dtype, chunk_dims, offset_data, coeff);
if (rc_write != TREXIO_SUCCESS) return rc_write;
}
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_hdf5_read_determinant_coefficient_size (trexio_t* const file, int64_t* const size_max)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (size_max == NULL) return TREXIO_INVALID_ARG_2;
char dset_coeff_name[128];
memset(dset_coeff_name, 0, sizeof(dset_coeff_name));
const int32_t trexio_state = file->state;
if (trexio_state != 0) {
sprintf(dset_coeff_name, "determinant_coefficient_state_%" PRId32, trexio_state);
} else {
strncpy(dset_coeff_name, "determinant_coefficient", 24);
}
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
hid_t dset_id = H5Dopen(f->determinant_group, dset_coeff_name, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
hid_t fspace_id = H5Dget_space(dset_id);
if (fspace_id < 0) {
H5Dclose(dset_id);
return TREXIO_INVALID_ID;
}
// allocate space for the dimensions to be read
hsize_t ddims[1] = {0};
// get the rank and dimensions of the dataset
H5Sget_simple_extent_dims(fspace_id, ddims, NULL);
H5Dclose(dset_id);
H5Sclose(fspace_id);
*size_max = (int64_t) ddims[0];
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle has_determinant_hdf5.c
trexio_exit_code trexio_hdf5_has_determinant_list(trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
if (f->determinant_group == (hsize_t) 0) return TREXIO_HAS_NOT;
herr_t status = H5LTfind_dataset(f->determinant_group, "determinant_list");
/* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */
if (status == 1){
return TREXIO_SUCCESS;
} else if (status == 0) {
return TREXIO_HAS_NOT;
} else {
return TREXIO_FAILURE;
}
}
trexio_exit_code trexio_hdf5_has_determinant_coefficient(trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
if (f->determinant_group == (hsize_t) 0) return TREXIO_HAS_NOT;
char dset_coeff_name[128];
memset(dset_coeff_name, 0, sizeof(dset_coeff_name));
const int32_t trexio_state = file->state;
if (trexio_state != 0) {
sprintf(dset_coeff_name, "determinant_coefficient_state_%" PRId32, trexio_state);
} else {
strncpy(dset_coeff_name, "determinant_coefficient", 24);
}
herr_t status = H5LTfind_dataset(f->determinant_group, dset_coeff_name);
/* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */
if (status == 1){
return TREXIO_SUCCESS;
} else if (status == 0) {
return TREXIO_HAS_NOT;
} else {
return TREXIO_FAILURE;
}
}
#+end_src
* Helper functions
#+begin_src c :tangle helpers_hdf5.c
@ -1113,6 +1375,7 @@ trexio_hdf5_open_write_dset_sparse (const hid_t group_id,
trexio_exit_code
trexio_hdf5_open_read_dset_sparse (const hid_t group_id,
const char* dset_name,
const uint32_t dset_rank,
const hsize_t* offset_file,
hsize_t* const size_read,
int64_t* const eof_read_size,
@ -1121,6 +1384,7 @@ trexio_hdf5_open_read_dset_sparse (const hid_t group_id,
)
{
const int h5_rank = 1;
if (dset_rank == 0) return TREXIO_INVALID_ARG_3;
// get the dataset handle
hid_t dset_id = H5Dopen(group_id, dset_name, H5P_DEFAULT);
@ -1151,9 +1415,9 @@ trexio_hdf5_open_read_dset_sparse (const hid_t group_id,
if (max_offset > ddims[0]) {
is_EOF = 1;
// lower the value of count to reduce the number of elements which will be read
size_read[0] -= max_offset - ddims[0];
size_read[0] -= (max_offset - ddims[0]);
// modified the value of eof_read_size passed by address
if (eof_read_size != NULL) *eof_read_size = size_read[0];
if (eof_read_size != NULL) *eof_read_size = size_read[0]/dset_rank;
}
// special case when reading int indices
@ -1238,7 +1502,7 @@ trexio_hdf5_open_read_dset_sparse (const hid_t group_id,
#+begin_src c :tangle suffix_hdf5.h
trexio_exit_code trexio_hdf5_create_write_dset_sparse (const hid_t group_id, const char* dset_name, const hid_t dtype_id, const hsize_t* chunk_dims, const void* data_sparse);
trexio_exit_code trexio_hdf5_open_write_dset_sparse (const hid_t group_id, const char* dset_name, const hid_t dtype_id, const hsize_t* chunk_dims, const hsize_t* offset_file, const void* data_sparse);
trexio_exit_code trexio_hdf5_open_read_dset_sparse (const hid_t group_id, const char* dset_name, const hsize_t* offset_file, hsize_t* const size_read, int64_t* const eof_read_size, const int is_index, void* const data_sparse);
trexio_exit_code trexio_hdf5_open_read_dset_sparse (const hid_t group_id, const char* dset_name, const uint32_t dset_rank, const hsize_t* offset_file, hsize_t* const size_read, int64_t* const eof_read_size, const int is_index, void* const data_sparse);
#endif
#+end_src

View File

@ -10,6 +10,9 @@ cat populated/pop_struct_text_group_dset.h >> trexio_text.h
cat populated/pop_struct_text_group.h >> trexio_text.h
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_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

View File

@ -3,6 +3,18 @@
#+SETUPFILE: ../../docs/theme.setup
# -*- mode: org -*-
The "file" produced by the text back end is a directory with one
file per group.
When the file is open, it is locked by the current process. No other
process can read/write the same file. This guarantees that the
representation in memory is consistent with the file and avoid
re-reading the file before writing.
To lock the file, we lock the =.lock= file which is present in the
directory.
The file is written when closed, or when the flush function is called.
* Constant file prefixes (not used by the generator) :noexport:
#+begin_src emacs-lisp
@ -61,21 +73,7 @@
#+end_src
* TEXT back end
The "file" produced by the text back end is a directory with one
file per group.
When the file is open, it is locked by the current process. No other
process can read/write the same file. This guarantees that the
representation in memory is consistent with the file and avoid
re-reading the file before writing.
To lock the file, we lock the =.lock= file which is present in the
directory.
The file is written when closed, or when the flush function is called.
** Template for group-related structures in text back end
* Template for group-related structures in text back end
#+begin_src c :tangle struct_text_group_dset.h
typedef struct $group$_s {
@ -91,7 +89,7 @@ typedef struct $group$_s {
} $group$_t;
#+end_src
** Template for general structure in text back end
* Template for general structure in text back end
#+begin_src c :tangle struct_text_group.h
typedef struct trexio_text_s {
@ -101,7 +99,7 @@ typedef struct trexio_text_s {
} trexio_text_t;
#+end_src
** Initialize function (constant part)
* Initialize function (constant part)
#+begin_src c :tangle basic_text.h :exports none
trexio_exit_code trexio_text_init(trexio_t* const file);
@ -246,7 +244,7 @@ trexio_text_unlock (trexio_t* const file)
}
#+end_src
** Deinitialize function (templated part)
* Deinitialize function (templated part)
#+begin_src c :tangle basic_text_group.c
trexio_exit_code
@ -265,7 +263,7 @@ trexio_text_deinit (trexio_t* const file)
}
#+end_src
** Template for text read a group
* Template for text read a group
#+begin_src c :tangle read_group_text.h :exports none
$group$_t* trexio_text_read_$group$(trexio_text_t* const file);
@ -567,7 +565,7 @@ trexio_text_read_$group$ (trexio_text_t* const file)
}
#+end_src
** Template for text flush a group
* Template for text flush a group
#+begin_src c :tangle flush_group_text.h :exports none
trexio_exit_code trexio_text_flush_$group$(trexio_text_t* const file);
@ -632,7 +630,7 @@ trexio_text_flush_$group$ (trexio_text_t* const file)
}
#+end_src
** Template for text free memory
* Template for text free memory
Memory is allocated when reading. The following function frees memory.
@ -678,7 +676,7 @@ trexio_text_free_$group$ (trexio_text_t* const file)
}
#+end_src
** Template for has/read/write a numerical attribute
* Template for has/read/write a numerical attribute
#+begin_src c :tangle hrw_attr_num_text.h :exports none
trexio_exit_code trexio_text_has_$group_num$ (trexio_t* const file);
@ -742,7 +740,7 @@ trexio_text_has_$group_num$ (trexio_t* const file)
}
#+end_src
** Template for has/read/write a dataset of numerical data
* Template for has/read/write a dataset of numerical data
The ~group_dset~ array is assumed allocated with the appropriate size.
@ -837,7 +835,7 @@ trexio_text_has_$group_dset$ (trexio_t* const file)
}
#+end_src
** Template for has/read/write a dataset of strings
* Template for has/read/write a dataset of strings
The ~group_dset~ array is assumed allocated with the appropriate size.
@ -937,7 +935,7 @@ trexio_text_has_$group_dset$ (trexio_t* const file)
}
#+end_src
** Template for has/read/write a string attribute
* Template for has/read/write a string attribute
#+begin_src c :tangle hrw_attr_str_text.h :exports none
trexio_exit_code trexio_text_has_$group_str$ (trexio_t* const file);
@ -1012,7 +1010,7 @@ trexio_text_has_$group_str$ (trexio_t* const file)
}
#+end_src
** Template for has/read/write the dataset of sparse data
* Template for has/read/write the dataset of sparse data
Each sparse array is stored in a separate =.txt= file due to the fact that sparse I/O has to be decoupled
from conventional write/read/flush behaviour of the TEXT back end. Chunks are used to read/write sparse data
@ -1284,7 +1282,7 @@ trexio_exit_code trexio_text_has_$group_dset$(trexio_t* const file)
}
#+end_src
** Template for text delete a group (UNSAFE mode)
* Template for text delete a group (UNSAFE mode)
#+begin_src c :tangle delete_group_text.h :exports none
trexio_exit_code trexio_text_delete_$group$ (trexio_t* const file);
@ -1313,6 +1311,411 @@ trexio_text_delete_$group$ (trexio_t* const file)
}
#+end_src
* Source code for the determinant part
Each array is stored in a separate =.txt= file due to the fact that determinant I/O has to be decoupled
from conventional write/read/flush behaviour of the TEXT back end. Chunks are used to read/write the data
to prevent memory overflow. Chunks have a given ~int64_t size~.
Size specifies the number of data items, e.g. determinants.
#+begin_src c :tangle hrw_determinant_text.h :exports none
trexio_exit_code trexio_text_has_determinant_list(trexio_t* const file);
trexio_exit_code trexio_text_read_determinant_list(trexio_t* const file, const int64_t offset_file, const uint32_t rank, const uint64_t* dims, int64_t* const eof_read_size, int64_t* const list);
trexio_exit_code trexio_text_write_determinant_list(trexio_t* const file, const int64_t offset_file, const uint32_t rank, const uint64_t* dims, const int64_t* list);
trexio_exit_code trexio_text_has_determinant_coefficient(trexio_t* const file);
trexio_exit_code trexio_text_read_determinant_coefficient(trexio_t* const file, const int64_t offset_file, const uint32_t rank, const uint64_t* dims, int64_t* const eof_read_size, double* const coeff);
trexio_exit_code trexio_text_write_determinant_coefficient(trexio_t* const file, const int64_t offset_file, const uint32_t rank, const uint64_t* dims, const double* coeff);
trexio_exit_code trexio_text_read_determinant_coefficient_size(trexio_t* const file, int64_t* const size_max);
#+end_src
#+begin_src c :tangle read_determinant_text.c
trexio_exit_code trexio_text_read_determinant_list(trexio_t* const file,
const int64_t offset_file,
const uint32_t rank,
const uint64_t* dims,
int64_t* const eof_read_size,
int64_t* const list)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5;
if (list == NULL) return TREXIO_INVALID_ARG_6;
const char determinant_list_file_name[256] = "/determinant_list.txt";
/* The full path to the destination TXT file with sparse data. This will include TREXIO directory name. */
char file_full_path[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, determinant_list_file_name,
TREXIO_MAX_FILENAME_LENGTH-strlen(determinant_list_file_name));
/* Open the file in "r" (read) mode to guarantee that no truncation happens upon consecutive reads */
FILE* f = fopen(file_full_path, "r");
if(f == NULL) return TREXIO_FILE_ERROR;
/* Specify the line length in order to offset properly.
Each 64-bit integer takes at most 10 slots and requires one space,
we have int_num integers per up-spin determinant,
then this number is doubled because we have the same number for down-spin electrons,
and then one newline char.
,*/
uint64_t line_length = dims[1]*11UL + 1UL; // 10 digits per int64_t bitfield + 1 space = 11 spots + 1 newline char
/* Offset in the file according to the provided value of offset_file and optimal line_length */
fseek(f, (long) offset_file * line_length, SEEK_SET);
/* Read the data from the file and check the return code of fprintf to verify that > 0 bytes have been read or reached EOF */
int rc;
/* Declare fixed buffer which will be used to read the determinant string <a1 a2 ... a/\ b1 b2 ... b\/> */
char buffer[1024];
uint32_t buf_size = sizeof(buffer);
/* Parameters to post-process the buffer and to get bit fields integers */
uint64_t accum = 0UL;
uint32_t shift_int64 = 11U;
/* Counter for number of elements beind processed */
uint64_t count = 0UL;
for (uint64_t i=0UL; i < dims[0]; ++i) {
accum = 0UL;
memset(buffer, 0, buf_size);
if(fgets(buffer, buf_size-1, f) == NULL){
fclose(f);
,*eof_read_size = count;
return TREXIO_END;
} else {
/* The format string is not anymore static but rather dynamic (the number of ints depend on the mo_num)
Thus, we parse the buffer string int_num*2 times to get the bit field determinants.
,*/
for (uint32_t j=0; j < (uint32_t) dims[1]; ++j) {
rc = sscanf(buffer+accum, "%10" SCNd64, list + dims[1]*i + j);
if(rc <= 0) {
fclose(f);
return TREXIO_FAILURE;
}
accum += shift_int64;
}
count += 1UL;
}
}
/* Close the TXT file */
rc = fclose(f);
if(rc != 0) return TREXIO_FILE_ERROR;
return TREXIO_SUCCESS;
}
trexio_exit_code trexio_text_read_determinant_coefficient(trexio_t* const file,
const int64_t offset_file,
const uint32_t rank,
const uint64_t* dims,
int64_t* const eof_read_size,
double* const coeff)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (eof_read_size == NULL) return TREXIO_INVALID_ARG_5;
if (coeff == NULL) return TREXIO_INVALID_ARG_6;
char coeff_file_name[256];
memset(coeff_file_name, 0, sizeof(coeff_file_name));
const int32_t trexio_state = file->state;
if (trexio_state != 0) {
sprintf(coeff_file_name, "/determinant_coefficient_state_%" PRId32 ".txt", trexio_state);
} else {
strncpy(coeff_file_name, "/determinant_coefficient.txt", 32);
}
/* The full path to the destination TXT file with sparse data. This will include TREXIO directory name. */
char file_full_path[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, coeff_file_name,
TREXIO_MAX_FILENAME_LENGTH-strlen(coeff_file_name));
/* Open the file in "r" (read) mode to guarantee that no truncation happens upon consecutive reads */
FILE* f = fopen(file_full_path, "r");
if(f == NULL) return TREXIO_FILE_ERROR;
/* Specify the line length in order to offset properly.
Each double value 24 elements + one newline char.
,*/
uint64_t line_length = 25UL;
/* Offset in the file according to the provided value of offset_file and optimal line_length */
fseek(f, (long) offset_file * line_length, SEEK_SET);
/* Read the data from the file and check the return code of fprintf to verify that > 0 bytes have been read or reached EOF */
int rc;
/* Declare fixed buffer which will be used to read the determinant string <a1 a2 ... a/\ b1 b2 ... b\/> */
char buffer[64];
uint32_t buf_size = sizeof(buffer);
/* Counter for number of elements beind processed */
uint64_t count = 0UL;
for (uint64_t i=0UL; i < dims[0]; ++i) {
memset(buffer, 0, buf_size);
if(fgets(buffer, buf_size-1, f) == NULL){
fclose(f);
,*eof_read_size = count;
return TREXIO_END;
} else {
rc = sscanf(buffer, "%lf", coeff + i);
if(rc <= 0) {
fclose(f);
return TREXIO_FAILURE;
}
count += 1UL;
}
}
/* Close the TXT file */
rc = fclose(f);
if(rc != 0) return TREXIO_FILE_ERROR;
return TREXIO_SUCCESS;
}
trexio_exit_code
trexio_text_read_determinant_coefficient_size(trexio_t* const file, int64_t* const size_max)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (size_max == NULL) return TREXIO_INVALID_ARG_2;
char coeff_file_name[256];
memset(coeff_file_name, 0, sizeof(coeff_file_name));
const int32_t trexio_state = file->state;
if (trexio_state != 0) {
sprintf(coeff_file_name, "/determinant_coefficient_state_%" PRId32 ".txt.size", trexio_state);
} else {
strncpy(coeff_file_name, "/determinant_coefficient.txt.size", 64);
}
/* The full path to the destination TXT file with sparse data. This will include TREXIO directory name. */
char file_full_path[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, coeff_file_name,
TREXIO_MAX_FILENAME_LENGTH-strlen(coeff_file_name));
/* Open the file in "r" (read) mode to guarantee that no truncation happens upon consecutive reads */
FILE* f = fopen(file_full_path, "r");
if(f == NULL) return TREXIO_FILE_ERROR;
/* Read the data from the file and check the return code of fprintf to verify that > 0 bytes have been read or reached EOF */
int rc;
int64_t size_item, size_accum=0L;
/* Read the values from the file. BEWARE OF POSSIBLE MAX_INT64 OVERFLOW ! */
while(fscanf(f, "%" SCNd64, &size_item) != EOF) {
/* Check that summation will not overflow the int64_t value */
if (INT64_MAX - size_accum > size_item) {
size_accum += size_item;
} else {
fclose(f);
,*size_max = -1L;
return TREXIO_INT_SIZE_OVERFLOW;
}
}
/* Close the TXT file */
rc = fclose(f);
if(rc != 0) return TREXIO_FILE_ERROR;
/* Overwrite the value at the input address and return TREXIO_SUCCESS */
,*size_max = size_accum;
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle write_determinant_text.c
trexio_exit_code trexio_text_write_determinant_list(trexio_t* const file,
const int64_t offset_file,
const uint32_t rank,
const uint64_t* dims,
const int64_t* list)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (list == NULL) return TREXIO_INVALID_ARG_5;
const char determinant_list_file_name[256] = "/determinant_list.txt";
/* The full path to the destination TXT file with sparse data. This will include TREXIO directory name. */
char file_full_path[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, determinant_list_file_name,
TREXIO_MAX_FILENAME_LENGTH-strlen(determinant_list_file_name));
/* Open the file in "a" (append) mode to guarantee that no truncation happens upon consecutive writes */
FILE* f = fopen(file_full_path, "a");
if(f == NULL) return TREXIO_FILE_ERROR;
/* Write the data in the file and check the return code of fprintf to verify that > 0 bytes have been written */
int rc;
for (uint64_t i=0UL; i < dims[0]; ++i) {
/* The loop below is needed to write a line with int bit fields for alpha and beta electrons */
for (uint32_t j=0; j < (uint32_t) dims[1]; ++j) {
rc = fprintf(f, "%10" PRId64 " ", *(list + i*dims[1] + j));
if(rc <= 0) {
fclose(f);
return TREXIO_FAILURE;
}
}
fprintf(f, "%s", "\n");
}
/* Close the TXT file */
rc = fclose(f);
if (rc != 0) return TREXIO_FILE_ERROR;
/* Exit upon success */
return TREXIO_SUCCESS;
}
trexio_exit_code trexio_text_write_determinant_coefficient(trexio_t* const file,
const int64_t offset_file,
const uint32_t rank,
const uint64_t* dims,
const double* coeff)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (coeff == NULL) return TREXIO_INVALID_ARG_5;
char coeff_file_name[256];
memset(coeff_file_name, 0, sizeof(coeff_file_name));
const int32_t trexio_state = file->state;
if (trexio_state != 0) {
sprintf(coeff_file_name, "/determinant_coefficient_state_%" PRId32 ".txt", trexio_state);
} else {
strncpy(coeff_file_name, "/determinant_coefficient.txt", 32);
}
/* The full path to the destination TXT file with sparse data. This will include TREXIO directory name. */
char file_full_path[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, coeff_file_name,
TREXIO_MAX_FILENAME_LENGTH-strlen(coeff_file_name));
/* Open the file in "a" (append) mode to guarantee that no truncation happens upon consecutive writes */
FILE* f = fopen(file_full_path, "a");
if(f == NULL) return TREXIO_FILE_ERROR;
/* Write the data in the file and check the return code of fprintf to verify that > 0 bytes have been written */
int rc;
for (uint64_t i=0UL; i < dims[0]; ++i) {
rc = fprintf(f, "%24.16e\n", *(coeff + i));
if(rc <= 0) {
fclose(f);
return TREXIO_FAILURE;
}
}
/* Close the TXT file */
rc = fclose(f);
if (rc != 0) return TREXIO_FILE_ERROR;
/* Append .size to the file_full_path in order to write additional info about the written buffer of data */
strncat(file_full_path, ".size", 6);
/* Open the new file in "a" (append) mode to append info about the buffer that has been just written */
FILE *f_wSize = fopen(file_full_path, "a");
if (f_wSize == NULL) return TREXIO_FILE_ERROR;
/* Write the buffer_size */
rc = fprintf(f_wSize, "%" PRIu64 "\n", dims[0]);
if (rc <= 0) {
fclose(f_wSize);
return TREXIO_FAILURE;
}
/* Close the TXT file */
rc = fclose(f_wSize);
if (rc != 0) return TREXIO_FILE_ERROR;
/* Exit upon success */
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle has_determinant_text.c
trexio_exit_code trexio_text_has_determinant_list(trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
const char determinant_list_file_name[256] = "/determinant_list.txt";
/* The full path to the destination TXT file with sparse data. This will include TREXIO directory name. */
char file_full_path[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, determinant_list_file_name,
TREXIO_MAX_FILENAME_LENGTH-strlen(determinant_list_file_name));
/* Check the return code of access function to determine whether the file with data exists or not */
if (access(file_full_path, F_OK) == 0){
return TREXIO_SUCCESS;
} else {
return TREXIO_HAS_NOT;
}
}
trexio_exit_code trexio_text_has_determinant_coefficient(trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
char coeff_file_name[256];
memset(coeff_file_name, 0, sizeof(coeff_file_name));
const int32_t trexio_state = file->state;
if (trexio_state != 0) {
sprintf(coeff_file_name, "/determinant_coefficient_state_%" PRId32 ".txt", trexio_state);
} else {
strncpy(coeff_file_name, "/determinant_coefficient.txt", 32);
}
/* The full path to the destination TXT file with sparse data. This will include TREXIO directory name. */
char file_full_path[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, coeff_file_name,
TREXIO_MAX_FILENAME_LENGTH-strlen(coeff_file_name));
/* Check the return code of access function to determine whether the file with data exists or not */
if (access(file_full_path, F_OK) == 0){
return TREXIO_SUCCESS;
} else {
return TREXIO_HAS_NOT;
}
}
#+end_src
* Constant file suffixes (not used by the generator) :noexport:
#+begin_src c :tangle suffix_text.h

View File

@ -7,6 +7,7 @@ set(Tests_text
io_dset_float_text
io_dset_str_text
io_dset_sparse_text
io_determinant_text
io_safe_dset_float_text
io_dset_int_text
io_num_text
@ -23,6 +24,7 @@ if(ENABLE_HDF5)
io_dset_float_hdf5
io_dset_str_hdf5
io_dset_sparse_hdf5
io_determinant_hdf5
io_safe_dset_float_hdf5
io_dset_int_hdf5
io_num_hdf5

340
tests/io_determinant_hdf5.c Normal file
View File

@ -0,0 +1,340 @@
#include "trexio.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define TEST_BACKEND TREXIO_HDF5
#define TREXIO_FILE "test_determinant.h5"
#define RM_COMMAND "rm -f " TREXIO_FILE
#define SIZE 100
#define N_CHUNKS 5
#define STATE_TEST 2
#define MO_NUM 150
static int test_write_determinant (const char* file_name, const back_end_t backend, const int64_t offset) {
/* Try to write an array of sparse data into the TREXIO file */
trexio_t* file = NULL;
trexio_exit_code rc;
/*================= START OF TEST ==================*/
// open file in 'write' mode
file = trexio_open(file_name, 'w', backend, &rc);
assert (file != NULL);
assert (rc == TREXIO_SUCCESS);
// parameters to be written
int64_t* det_list;
double* det_coef;
int mo_num = MO_NUM;
det_list = (int64_t*) calloc(2*3*SIZE, sizeof(int64_t));
det_coef = (double*) calloc(SIZE, sizeof(double));
for(int i=0; i<SIZE; i++){
det_list[6*i] = 6*i;
det_list[6*i+1] = 6*i+1;
det_list[6*i+2] = 6*i+2;
det_list[6*i+3] = 6*i+3;
det_list[6*i+4] = 6*i+4;
det_list[6*i+5] = 6*i+5;
det_coef[i] = 3.14 + (double) i;
}
// write mo_num which will be used to determine the optimal size of int indices
if (trexio_has_mo_num(file) == TREXIO_HAS_NOT) {
rc = trexio_write_mo_num(file, mo_num);
assert(rc == TREXIO_SUCCESS);
}
// write dataset chunks of sparse data in the file (including FAKE statements)
uint64_t chunk_size = (uint64_t) SIZE/N_CHUNKS;
uint64_t offset_f = 0UL;
uint64_t offset_d = 0UL;
if (offset != 0L) offset_f += offset;
// write n_chunks times using write_sparse
for(int i=0; i<N_CHUNKS; ++i){
rc = trexio_write_determinant_list(file, offset_f, chunk_size, &det_list[6*offset_d]);
assert(rc == TREXIO_SUCCESS);
rc = trexio_write_determinant_coefficient(file, offset_f, chunk_size, &det_coef[offset_d]);
assert(rc == TREXIO_SUCCESS);
// The block below will write the coefficients for STATE_TEST
rc = trexio_set_state(file, STATE_TEST);
assert(rc == TREXIO_SUCCESS);
rc = trexio_write_determinant_coefficient(file, offset_f, chunk_size, &det_coef[offset_d]);
assert(rc == TREXIO_SUCCESS);
// set state back to the default 0 (ground state)
rc = trexio_set_state(file, 0);
assert(rc == TREXIO_SUCCESS);
// =================================================
offset_d += chunk_size;
offset_f += chunk_size;
}
// manually check the consistency of the determinant_num and coefficient_size after writing
int64_t coeff_size = 0L;
int64_t determinant_num = 0L;
rc = trexio_read_determinant_num_64(file, &determinant_num);
assert(rc == TREXIO_SUCCESS);
rc = trexio_read_determinant_coefficient_size(file, &coeff_size);
assert(rc == TREXIO_SUCCESS);
assert(determinant_num == coeff_size);
rc = trexio_set_state(file, STATE_TEST);
assert(rc == TREXIO_SUCCESS);
rc = trexio_read_determinant_coefficient_size(file, &coeff_size);
assert(rc == TREXIO_SUCCESS);
assert(determinant_num == coeff_size);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
// free the allocated memeory
free(det_list);
free(det_coef);
/*================= END OF TEST ==================*/
return 0;
}
static int test_has_determinant(const char* file_name, const back_end_t backend) {
/* Try to check the existence of a dataset of sparse data in the TREXIO file */
trexio_t* file = NULL;
trexio_exit_code rc;
/*================= START OF TEST ==================*/
// open file
file = trexio_open(file_name, 'r', backend, &rc);
assert (file != NULL);
assert (rc == TREXIO_SUCCESS);
// now check that previously written determinant_list exists
rc = trexio_has_determinant_list(file);
assert(rc==TREXIO_SUCCESS);
// now check that previously written determinant_coefficient exists
rc = trexio_has_determinant_coefficient(file);
assert(rc==TREXIO_SUCCESS);
// also check for STATE_TEST
rc = trexio_set_state(file, STATE_TEST);
assert(rc == TREXIO_SUCCESS);
rc = trexio_has_determinant_coefficient(file);
assert(rc==TREXIO_SUCCESS);
rc = trexio_set_state(file, 0);
assert(rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
/*================= END OF TEST ==================*/
return 0;
}
static int test_read_determinant (const char* file_name, const back_end_t backend, const int64_t offset) {
/* Try to read one chunk of dataset of sparse data in the TREXIO file */
trexio_t* file = NULL;
trexio_exit_code rc;
/*================= START OF TEST ==================*/
// open file
file = trexio_open(file_name, 'r', backend, &rc);
assert (file != NULL);
assert (rc == TREXIO_SUCCESS);
// compute how many integer bit fields is needed per determinant (for a given spin)
int64_t mo_num;
rc = trexio_read_mo_num_64(file, &mo_num);
assert (rc == TREXIO_SUCCESS);
assert (mo_num == MO_NUM);
int int_num = (mo_num - 1)/64 + 1;
assert (int_num == 3);
// define arrays to read into
int64_t* det_list_read;
double* det_coef_read;
double* det_coef_s2_read;
double check_diff;
uint64_t size_r = 40L;
det_list_read = (int64_t*) calloc(2*int_num*size_r,sizeof(int64_t));
det_coef_read = (double*) calloc(size_r,sizeof(double));
det_coef_s2_read = (double*) calloc(size_r,sizeof(double));
// specify the read parameters, here:
// 1 chunk of 10 elements using offset of 40 (i.e. lines No. 40--59) into elements of the array starting from 5
int64_t chunk_read = 10L;
int64_t offset_file_read = 40L;
int offset_data_read = 5;
int64_t read_size_check;
read_size_check = chunk_read;
if (offset != 0L) offset_file_read += offset;
// read one chunk using the aforementioned parameters
rc = trexio_read_determinant_list(file, offset_file_read, &chunk_read, &det_list_read[2*int_num*offset_data_read]);
assert(rc == TREXIO_SUCCESS);
assert(chunk_read == read_size_check);
assert(det_list_read[0] == 0);
assert(det_list_read[2*int_num*offset_data_read] == 2 * int_num * (int64_t) (offset_file_read-offset));
rc = trexio_read_determinant_coefficient(file, offset_file_read, &chunk_read, &det_coef_read[offset_data_read]);
assert(rc == TREXIO_SUCCESS);
assert(chunk_read == read_size_check);
check_diff = det_coef_read[0] - 0.;
assert(check_diff*check_diff < 1e-14);
check_diff = det_coef_read[offset_data_read] - (3.14 + (double) (offset_file_read-offset));
//printf("%lf %lf\n", check_diff, det_coef_read[offset_data_read]);
assert(check_diff*check_diff < 1e-14);
// read one chuk of coefficients for a different state
rc = trexio_set_state(file, STATE_TEST);
assert(rc == TREXIO_SUCCESS);
rc = trexio_read_determinant_coefficient(file, offset_file_read, &chunk_read, &det_coef_s2_read[offset_data_read]);
assert(rc == TREXIO_SUCCESS);
assert(chunk_read == read_size_check);
check_diff = det_coef_s2_read[0] - 0.;
assert(check_diff*check_diff < 1e-14);
rc = trexio_set_state(file, 0);
assert(rc == TREXIO_SUCCESS);
// now attempt to read so that one encounters end of file during reading (i.e. offset_file_read + chunk_read > size_max)
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
if (offset != 0L) offset_file_read += offset;
chunk_read = read_size_check;
// read one chunk that will reach EOF and return TREXIO_END code
rc = trexio_read_determinant_list(file, offset_file_read, &chunk_read, &det_list_read[2*int_num*offset_data_read]);
/*
printf("%s\n", trexio_string_of_error(rc));
for (int i=0; i<size_r; i++) {
printf("%lld %lld\n", det_list_read[6*i], det_list_read[6*i+5]);
}
*/
assert(rc == TREXIO_END);
assert(chunk_read == eof_read_size_check);
assert(det_list_read[2*int_num*size_r-1] == 0);
assert(det_list_read[2*int_num*offset_data_read] == 2 * int_num * (int64_t) (offset_file_read-offset));
chunk_read = read_size_check;
rc = trexio_read_determinant_coefficient(file, offset_file_read, &chunk_read, &det_coef_read[offset_data_read]);
/*
printf("%s\n", trexio_string_of_error(rc));
for (int i=0; i<size_r; i++) {
printf("%lf\n", det_coef_read[i]);
}
*/
assert(rc == TREXIO_END);
assert(chunk_read == eof_read_size_check);
check_diff= det_coef_read[size_r-1] - 0.;
//printf("%lf %lf\n", check_diff, det_coef_read[size_r-1]);
assert(check_diff*check_diff < 1e-14);
// check the value of determinant_num
int32_t det_num = 0;
int32_t size_check = SIZE;
if (offset != 0L) size_check += offset;
rc = trexio_read_determinant_num(file, &det_num);
assert(rc == TREXIO_SUCCESS);
assert(det_num == size_check);
// check conversion of determinants into orbital lists
int64_t size_list = NORB_PER_INT * int_num;
int32_t* orb_list_up = (int32_t*) calloc(size_list, sizeof(int32_t));
int32_t* orb_list_dn = (int32_t*) calloc(size_list, sizeof(int32_t));
int32_t occ_num_up, occ_num_dn;
rc = trexio_to_orbital_list_up_dn (int_num, &det_list_read[2*int_num*5], orb_list_up, orb_list_dn, &occ_num_up, &occ_num_dn);
assert (rc == TREXIO_SUCCESS);
assert (occ_num_up == 14);
assert (occ_num_dn == 17);
/* // DEBUG printing
printf("occ_num_up : %d ; occ_num_dn : %d \n", occ_num_up, occ_num_dn);
for (int i=0; i<occ_num_up; i++) {
printf("%d ", orb_list_up[i]);
}
printf("| ");
for (int i=0; i<occ_num_dn; i++) {
printf("%d ", orb_list_dn[i]);
}
printf("\n");
*/
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
// free the memory
free(det_list_read);
free(det_coef_read);
free(det_coef_s2_read);
free(orb_list_up);
free(orb_list_dn);
/*================= END OF TEST ==================*/
return 0;
}
int main(){
/*============== Test launcher ================*/
int rc;
rc = system(RM_COMMAND);
assert (rc == 0);
// check the first write attempt (SIZE elements written in N_CHUNKS chunks)
test_write_determinant (TREXIO_FILE, TEST_BACKEND, 0);
test_has_determinant (TREXIO_FILE, TEST_BACKEND);
test_read_determinant (TREXIO_FILE, TEST_BACKEND, 0);
// check the second write attempt (SIZE elements written in N_CHUNKS chunks)
test_write_determinant (TREXIO_FILE, TEST_BACKEND, SIZE);
test_read_determinant (TREXIO_FILE, TEST_BACKEND, SIZE);
rc = system(RM_COMMAND);
assert (rc == 0);
return 0;
}

340
tests/io_determinant_text.c Normal file
View File

@ -0,0 +1,340 @@
#include "trexio.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define TEST_BACKEND TREXIO_TEXT
#define TREXIO_FILE "test_determinant.dir"
#define RM_COMMAND "rm -rf " TREXIO_FILE
#define SIZE 100
#define N_CHUNKS 5
#define STATE_TEST 2
#define MO_NUM 150
static int test_write_determinant (const char* file_name, const back_end_t backend, const int64_t offset) {
/* Try to write an array of sparse data into the TREXIO file */
trexio_t* file = NULL;
trexio_exit_code rc;
/*================= START OF TEST ==================*/
// open file in 'write' mode
file = trexio_open(file_name, 'w', backend, &rc);
assert (file != NULL);
assert (rc == TREXIO_SUCCESS);
// parameters to be written
int64_t* det_list;
double* det_coef;
int mo_num = MO_NUM;
det_list = (int64_t*) calloc(2*3*SIZE, sizeof(int64_t));
det_coef = (double*) calloc(SIZE, sizeof(double));
for(int i=0; i<SIZE; i++){
det_list[6*i] = 6*i;
det_list[6*i+1] = 6*i+1;
det_list[6*i+2] = 6*i+2;
det_list[6*i+3] = 6*i+3;
det_list[6*i+4] = 6*i+4;
det_list[6*i+5] = 6*i+5;
det_coef[i] = 3.14 + (double) i;
}
// write mo_num which will be used to determine the optimal size of int indices
if (trexio_has_mo_num(file) == TREXIO_HAS_NOT) {
rc = trexio_write_mo_num(file, mo_num);
assert(rc == TREXIO_SUCCESS);
}
// write dataset chunks of sparse data in the file (including FAKE statements)
uint64_t chunk_size = (uint64_t) SIZE/N_CHUNKS;
uint64_t offset_f = 0UL;
uint64_t offset_d = 0UL;
if (offset != 0L) offset_f += offset;
// write n_chunks times using write_sparse
for(int i=0; i<N_CHUNKS; ++i){
rc = trexio_write_determinant_list(file, offset_f, chunk_size, &det_list[6*offset_d]);
assert(rc == TREXIO_SUCCESS);
rc = trexio_write_determinant_coefficient(file, offset_f, chunk_size, &det_coef[offset_d]);
assert(rc == TREXIO_SUCCESS);
// The block below will write the coefficients for STATE_TEST
rc = trexio_set_state(file, STATE_TEST);
assert(rc == TREXIO_SUCCESS);
rc = trexio_write_determinant_coefficient(file, offset_f, chunk_size, &det_coef[offset_d]);
assert(rc == TREXIO_SUCCESS);
// set state back to the default 0 (ground state)
rc = trexio_set_state(file, 0);
assert(rc == TREXIO_SUCCESS);
// =================================================
offset_d += chunk_size;
offset_f += chunk_size;
}
// manually check the consistency of the determinant_num and coefficient_size after writing
int64_t coeff_size = 0L;
int64_t determinant_num = 0L;
rc = trexio_read_determinant_num_64(file, &determinant_num);
assert(rc == TREXIO_SUCCESS);
rc = trexio_read_determinant_coefficient_size(file, &coeff_size);
assert(rc == TREXIO_SUCCESS);
assert(determinant_num == coeff_size);
rc = trexio_set_state(file, STATE_TEST);
assert(rc == TREXIO_SUCCESS);
rc = trexio_read_determinant_coefficient_size(file, &coeff_size);
assert(rc == TREXIO_SUCCESS);
assert(determinant_num == coeff_size);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
// free the allocated memeory
free(det_list);
free(det_coef);
/*================= END OF TEST ==================*/
return 0;
}
static int test_has_determinant(const char* file_name, const back_end_t backend) {
/* Try to check the existence of a dataset of sparse data in the TREXIO file */
trexio_t* file = NULL;
trexio_exit_code rc;
/*================= START OF TEST ==================*/
// open file
file = trexio_open(file_name, 'r', backend, &rc);
assert (file != NULL);
assert (rc == TREXIO_SUCCESS);
// now check that previously written determinant_list exists
rc = trexio_has_determinant_list(file);
assert(rc==TREXIO_SUCCESS);
// now check that previously written determinant_coefficient exists
rc = trexio_has_determinant_coefficient(file);
assert(rc==TREXIO_SUCCESS);
// also check for STATE_TEST
rc = trexio_set_state(file, STATE_TEST);
assert(rc == TREXIO_SUCCESS);
rc = trexio_has_determinant_coefficient(file);
assert(rc==TREXIO_SUCCESS);
rc = trexio_set_state(file, 0);
assert(rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
/*================= END OF TEST ==================*/
return 0;
}
static int test_read_determinant (const char* file_name, const back_end_t backend, const int64_t offset) {
/* Try to read one chunk of dataset of sparse data in the TREXIO file */
trexio_t* file = NULL;
trexio_exit_code rc;
/*================= START OF TEST ==================*/
// open file
file = trexio_open(file_name, 'r', backend, &rc);
assert (file != NULL);
assert (rc == TREXIO_SUCCESS);
// compute how many integer bit fields is needed per determinant (for a given spin)
int64_t mo_num;
rc = trexio_read_mo_num_64(file, &mo_num);
assert (rc == TREXIO_SUCCESS);
assert (mo_num == MO_NUM);
int int_num = (mo_num - 1)/64 + 1;
assert (int_num == 3);
// define arrays to read into
int64_t* det_list_read;
double* det_coef_read;
double* det_coef_s2_read;
double check_diff;
uint64_t size_r = 40L;
det_list_read = (int64_t*) calloc(2*int_num*size_r,sizeof(int64_t));
det_coef_read = (double*) calloc(size_r,sizeof(double));
det_coef_s2_read = (double*) calloc(size_r,sizeof(double));
// specify the read parameters, here:
// 1 chunk of 10 elements using offset of 40 (i.e. lines No. 40--59) into elements of the array starting from 5
int64_t chunk_read = 10L;
int64_t offset_file_read = 40L;
int offset_data_read = 5;
int64_t read_size_check;
read_size_check = chunk_read;
if (offset != 0L) offset_file_read += offset;
// read one chunk using the aforementioned parameters
rc = trexio_read_determinant_list(file, offset_file_read, &chunk_read, &det_list_read[2*int_num*offset_data_read]);
assert(rc == TREXIO_SUCCESS);
assert(chunk_read == read_size_check);
assert(det_list_read[0] == 0);
assert(det_list_read[2*int_num*offset_data_read] == 2 * int_num * (int64_t) (offset_file_read-offset));
rc = trexio_read_determinant_coefficient(file, offset_file_read, &chunk_read, &det_coef_read[offset_data_read]);
assert(rc == TREXIO_SUCCESS);
assert(chunk_read == read_size_check);
check_diff = det_coef_read[0] - 0.;
assert(check_diff*check_diff < 1e-14);
check_diff = det_coef_read[offset_data_read] - (3.14 + (double) (offset_file_read-offset));
//printf("%lf %lf\n", check_diff, det_coef_read[offset_data_read]);
assert(check_diff*check_diff < 1e-14);
// read one chuk of coefficients for a different state
rc = trexio_set_state(file, STATE_TEST);
assert(rc == TREXIO_SUCCESS);
rc = trexio_read_determinant_coefficient(file, offset_file_read, &chunk_read, &det_coef_s2_read[offset_data_read]);
assert(rc == TREXIO_SUCCESS);
assert(chunk_read == read_size_check);
check_diff = det_coef_s2_read[0] - 0.;
assert(check_diff*check_diff < 1e-14);
rc = trexio_set_state(file, 0);
assert(rc == TREXIO_SUCCESS);
// now attempt to read so that one encounters end of file during reading (i.e. offset_file_read + chunk_read > size_max)
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
if (offset != 0L) offset_file_read += offset;
chunk_read = read_size_check;
// read one chunk that will reach EOF and return TREXIO_END code
rc = trexio_read_determinant_list(file, offset_file_read, &chunk_read, &det_list_read[2*int_num*offset_data_read]);
/*
printf("%s\n", trexio_string_of_error(rc));
for (int i=0; i<size_r; i++) {
printf("%lld %lld\n", det_list_read[6*i], det_list_read[6*i+5]);
}
*/
assert(rc == TREXIO_END);
assert(chunk_read == eof_read_size_check);
assert(det_list_read[2*int_num*size_r-1] == 0);
assert(det_list_read[2*int_num*offset_data_read] == 2 * int_num * (int64_t) (offset_file_read-offset));
chunk_read = read_size_check;
rc = trexio_read_determinant_coefficient(file, offset_file_read, &chunk_read, &det_coef_read[offset_data_read]);
/*
printf("%s\n", trexio_string_of_error(rc));
for (int i=0; i<size_r; i++) {
printf("%lf\n", det_coef_read[i]);
}
*/
assert(rc == TREXIO_END);
assert(chunk_read == eof_read_size_check);
check_diff= det_coef_read[size_r-1] - 0.;
//printf("%lf %lf\n", check_diff, det_coef_read[size_r-1]);
assert(check_diff*check_diff < 1e-14);
// check the value of determinant_num
int32_t det_num = 0;
int32_t size_check = SIZE;
if (offset != 0L) size_check += offset;
rc = trexio_read_determinant_num(file, &det_num);
assert(rc == TREXIO_SUCCESS);
assert(det_num == size_check);
// check conversion of determinants into orbital lists
int64_t size_list = NORB_PER_INT * int_num;
int32_t* orb_list_up = (int32_t*) calloc(size_list, sizeof(int32_t));
int32_t* orb_list_dn = (int32_t*) calloc(size_list, sizeof(int32_t));
int32_t occ_num_up, occ_num_dn;
rc = trexio_to_orbital_list_up_dn (int_num, &det_list_read[2*int_num*5], orb_list_up, orb_list_dn, &occ_num_up, &occ_num_dn);
assert (rc == TREXIO_SUCCESS);
assert (occ_num_up == 14);
assert (occ_num_dn == 17);
/* // DEBUG printing
printf("occ_num_up : %d ; occ_num_dn : %d \n", occ_num_up, occ_num_dn);
for (int i=0; i<occ_num_up; i++) {
printf("%d ", orb_list_up[i]);
}
printf("| ");
for (int i=0; i<occ_num_dn; i++) {
printf("%d ", orb_list_dn[i]);
}
printf("\n");
*/
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
// free the memory
free(det_list_read);
free(det_coef_read);
free(det_coef_s2_read);
free(orb_list_up);
free(orb_list_dn);
/*================= END OF TEST ==================*/
return 0;
}
int main(){
/*============== Test launcher ================*/
int rc;
rc = system(RM_COMMAND);
assert (rc == 0);
// check the first write attempt (SIZE elements written in N_CHUNKS chunks)
test_write_determinant (TREXIO_FILE, TEST_BACKEND, 0);
test_has_determinant (TREXIO_FILE, TEST_BACKEND);
test_read_determinant (TREXIO_FILE, TEST_BACKEND, 0);
// check the second write attempt (SIZE elements written in N_CHUNKS chunks)
test_write_determinant (TREXIO_FILE, TEST_BACKEND, SIZE);
test_read_determinant (TREXIO_FILE, TEST_BACKEND, SIZE);
rc = system(RM_COMMAND);
assert (rc == 0);
return 0;
}

View File

@ -55,7 +55,7 @@ subroutine test_write(file_name, back_end)
integer(trexio_exit_code) :: rc = 1
integer :: num, basis_shell_num
integer :: nucleus_num, mo_num, ao_num, basis_shell_num
integer :: basis_nucleus_index(24)
double precision :: charge(12)
@ -65,23 +65,37 @@ subroutine test_write(file_name, back_end)
character(len=:), allocatable :: label(:)
! sparse data
integer(4) :: index_sparse_mo_2e_int_eri(4,100)
double precision :: value_sparse_mo_2e_int_eri(100)
integer(4) :: index_sparse_ao_2e_int_eri(4,100)
double precision :: value_sparse_ao_2e_int_eri(100)
integer :: i, n_buffers = 5
integer(8) :: buf_size, offset
buf_size = 100/n_buffers
! determinants
integer*8 :: det_list(6, 50)
integer*8 :: det_num
integer :: i, j, n_buffers = 5
integer(8) :: buf_size_sparse, buf_size_det, offset
buf_size_sparse = 100/n_buffers
buf_size_det = 50/n_buffers
! fill sparse indices and values
do i = 1, 100
index_sparse_mo_2e_int_eri(1,i) = 4*i - 3
index_sparse_mo_2e_int_eri(2,i) = 4*i+1 - 3
index_sparse_mo_2e_int_eri(3,i) = 4*i+2 - 3
index_sparse_mo_2e_int_eri(4,i) = 4*i+3 - 3
value_sparse_mo_2e_int_eri(i) = 3.14 + float(i)
index_sparse_ao_2e_int_eri(1,i) = 4*i - 3
index_sparse_ao_2e_int_eri(2,i) = 4*i+1 - 3
index_sparse_ao_2e_int_eri(3,i) = 4*i+2 - 3
index_sparse_ao_2e_int_eri(4,i) = 4*i+3 - 3
value_sparse_ao_2e_int_eri(i) = 3.14 + float(i)
enddo
! fill determinant list
do i = 1, 50
do j = 1, 6
det_list(j,i) = 6*i+(j-1) - 5
enddo
enddo
! parameters to be written
num = 12
nucleus_num = 12
charge = (/ 6., 6., 6., 6., 6., 6., 1., 1., 1., 1., 1., 1. /)
coord = reshape( (/ 0.00000000d0, 1.39250319d0 , 0.00000000d0 , &
-1.20594314d0, 0.69625160d0 , 0.00000000d0 , &
@ -97,6 +111,10 @@ subroutine test_write(file_name, back_end)
0.00000000d0, 2.47304151d0 , 0.00000000d0 /), &
shape(coord) )
! the first dimension of det_list (6) corresponds to mo_num=150; adapt the former if the latter is changed
mo_num = 150
ao_num = 1000
basis_shell_num = 24
basis_nucleus_index = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 /)
@ -118,10 +136,13 @@ subroutine test_write(file_name, back_end)
rc = trexio_has_nucleus_charge(trex_file)
call trexio_assert(rc, TREXIO_HAS_NOT, 'SUCCESS HAS NOT 2')
rc = trexio_has_mo_2e_int_eri(trex_file)
rc = trexio_has_ao_2e_int_eri(trex_file)
call trexio_assert(rc, TREXIO_HAS_NOT, 'SUCCESS HAS NOT 3')
rc = trexio_write_nucleus_num(trex_file, num)
rc = trexio_has_determinant_list(trex_file)
call trexio_assert(rc, TREXIO_HAS_NOT, 'SUCCESS HAS NOT 4')
rc = trexio_write_nucleus_num(trex_file, nucleus_num)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE NUM')
rc = trexio_write_nucleus_charge(trex_file, charge)
@ -144,19 +165,33 @@ subroutine test_write(file_name, back_end)
rc = trexio_write_basis_nucleus_index(trex_file, basis_nucleus_index)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE INDEX')
! write mo_num which will be used to determine the optimal size of int indices
! write ao_num which will be used to determine the optimal size of int indices
if (trexio_has_ao_num(trex_file) == TREXIO_HAS_NOT) then
rc = trexio_write_ao_num(trex_file, ao_num)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE AO NUM')
endif
! write mo_num which will be used to determine the optimal size of the determinants bit fields
if (trexio_has_mo_num(trex_file) == TREXIO_HAS_NOT) then
rc = trexio_write_mo_num(trex_file, 1000)
rc = trexio_write_mo_num(trex_file, mo_num)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE MO NUM')
endif
offset = 0
do i = 1,n_buffers
rc = trexio_write_mo_2e_int_eri(trex_file, offset, buf_size, &
index_sparse_mo_2e_int_eri(1,offset+1), &
value_sparse_mo_2e_int_eri(offset+1))
rc = trexio_write_ao_2e_int_eri(trex_file, offset, buf_size_sparse, &
index_sparse_ao_2e_int_eri(1,offset+1), &
value_sparse_ao_2e_int_eri(offset+1))
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE SPARSE')
offset = offset + buf_size
offset = offset + buf_size_sparse
enddo
offset = 0
do i = 1,n_buffers
rc = trexio_write_determinant_list(trex_file, offset, buf_size_det, &
det_list(1,offset+1))
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE DET LIST')
offset = offset + buf_size_det
enddo
rc = trexio_has_nucleus_num(trex_file)
@ -165,9 +200,12 @@ subroutine test_write(file_name, back_end)
rc = trexio_has_nucleus_coord(trex_file)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS HAS 2')
rc = trexio_has_mo_2e_int_eri(trex_file)
rc = trexio_has_ao_2e_int_eri(trex_file)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS HAS 3')
rc = trexio_has_determinant_list(trex_file)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS HAS 4')
rc = trexio_close(trex_file)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS CLOSE')
@ -203,8 +241,8 @@ subroutine test_read(file_name, back_end)
character(len=32) :: sym_str
! sparse data
integer(4) :: index_sparse_mo_2e_int_eri(4,20)
double precision :: value_sparse_mo_2e_int_eri(20)
integer(4) :: index_sparse_ao_2e_int_eri(4,20)
double precision :: value_sparse_ao_2e_int_eri(20)
integer(8) :: read_buf_size = 10
integer(8) :: read_buf_size_save = 10
integer(8) :: offset_read = 40
@ -213,13 +251,29 @@ subroutine test_read(file_name, back_end)
integer(8) :: offset_data_eof = 1
integer(8) :: size_toread = 0
! determinant data
integer*8 :: det_list(6,50)
integer*8 :: read_buf_det_size = 20
integer*8 :: offset_det_read = 10
integer*8 :: offset_det_data_read = 5
integer*8 :: determinant_num
! orbital lists
integer*4 :: orb_list_up(150)
integer*4 :: orb_list_dn(150)
integer*4 :: occ_num_up, occ_num_dn
character*(128) :: str
num = 12
basis_shell_num = 24
index_sparse_mo_2e_int_eri = 0
value_sparse_mo_2e_int_eri = 0.0d0
index_sparse_ao_2e_int_eri = 0
value_sparse_ao_2e_int_eri = 0.0d0
det_list = 0_8
orb_list_up = 0
orb_list_dn = 0
! ================= START OF TEST ===================== !
@ -289,15 +343,15 @@ subroutine test_read(file_name, back_end)
endif
rc = trexio_read_mo_2e_int_eri(trex_file, offset_read, read_buf_size, &
index_sparse_mo_2e_int_eri(1, offset_data_read + 1), &
value_sparse_mo_2e_int_eri(offset_data_read + 1))
rc = trexio_read_ao_2e_int_eri(trex_file, offset_read, read_buf_size, &
index_sparse_ao_2e_int_eri(1, offset_data_read + 1), &
value_sparse_ao_2e_int_eri(offset_data_read + 1))
!do i = 1,20
! write(*,*) index_sparse_mo_2e_int_eri(1,i)
! write(*,*) index_sparse_ao_2e_int_eri(1,i)
!enddo
call trexio_assert(rc, TREXIO_SUCCESS)
if (index_sparse_mo_2e_int_eri(1, 1) == 0 .and. &
index_sparse_mo_2e_int_eri(1, offset_data_read + 1) == offset_read*4 + 1) then
if (index_sparse_ao_2e_int_eri(1, 1) == 0 .and. &
index_sparse_ao_2e_int_eri(1, offset_data_read + 1) == offset_read*4 + 1) then
write(*,*) 'SUCCESS READ SPARSE DATA'
else
print *, 'FAILURE SPARSE DATA CHECK'
@ -307,17 +361,17 @@ subroutine test_read(file_name, back_end)
! attempt to read reaching EOF: should return TREXIO_END and
! NOT increment the existing values in the buffer (only upd with what has been read)
rc = trexio_read_mo_2e_int_eri(trex_file, offset_eof, read_buf_size, &
index_sparse_mo_2e_int_eri(1, offset_data_eof + 1), &
value_sparse_mo_2e_int_eri(offset_data_eof + 1))
rc = trexio_read_ao_2e_int_eri(trex_file, offset_eof, read_buf_size, &
index_sparse_ao_2e_int_eri(1, offset_data_eof + 1), &
value_sparse_ao_2e_int_eri(offset_data_eof + 1))
!do i = 1,20
! write(*,*) index_sparse_mo_2e_int_eri(1,i)
! write(*,*) index_sparse_ao_2e_int_eri(1,i)
!enddo
call trexio_assert(rc, TREXIO_END)
if (read_buf_size == 3 .and. &
index_sparse_mo_2e_int_eri(1, 1) == 0 .and. &
index_sparse_mo_2e_int_eri(1, offset_data_read + 1) == offset_read*4 + 1 .and. &
index_sparse_mo_2e_int_eri(1, offset_data_eof + 1) == offset_eof*4 + 1) then
index_sparse_ao_2e_int_eri(1, 1) == 0 .and. &
index_sparse_ao_2e_int_eri(1, offset_data_read + 1) == offset_read*4 + 1 .and. &
index_sparse_ao_2e_int_eri(1, offset_data_eof + 1) == offset_eof*4 + 1) then
write(*,*) 'SUCCESS READ SPARSE DATA EOF'
read_buf_size = read_buf_size_save
else
@ -325,7 +379,8 @@ subroutine test_read(file_name, back_end)
call exit(-1)
endif
rc = trexio_read_mo_2e_int_eri_size(trex_file, size_toread)
! read the size (number of integrals) of the sparse dataset
rc = trexio_read_ao_2e_int_eri_size(trex_file, size_toread)
call trexio_assert(rc, TREXIO_SUCCESS)
if (size_toread == 100) then
write(*,*) 'SUCCESS READ SPARSE SIZE'
@ -334,7 +389,45 @@ subroutine test_read(file_name, back_end)
call exit(-1)
endif
! read a chunk of determinants
rc = trexio_read_determinant_list(trex_file, offset_det_read, read_buf_det_size, &
det_list(1, offset_det_data_read + 1))
!do i = 1,50
! write(*,*) det_list(1,i)
!enddo
call trexio_assert(rc, TREXIO_SUCCESS)
if (det_list(1, 1) == 0 .and. &
det_list(1, offset_det_data_read + 1) == offset_det_read*6 + 1) then
write(*,*) 'SUCCESS READ DET LIST'
else
print *, 'FAILURE DET LIST CHECK'
call exit(-1)
endif
! read the total number of stored determinants
rc = trexio_read_determinant_num_64(trex_file, determinant_num)
call trexio_assert(rc, TREXIO_SUCCESS)
if (determinant_num == 50_8) then
write(*,*) 'SUCCESS READ DET NUM'
else
print *, 'FAILURE DET NUM CHECK'
call exit(-1)
endif
! convert one given determinant into lists of orbitals
rc = trexio_to_orbital_list_up_dn(3, det_list(:, offset_det_data_read+1), orb_list_up, orb_list_dn, occ_num_up, occ_num_dn)
!write(*,*) occ_num_up, occ_num_dn
!write(*,*) orb_list_up(1:occ_num_up)
!write(*,*) det_list(:, offset_det_data_read+1)
call trexio_assert(rc, TREXIO_SUCCESS)
if (occ_num_up == 16 .and. occ_num_dn == 5) then
write(*,*) 'SUCCESS CONVERT DET LIST'
else
print *, 'FAILURE DET CONVERT CHECK'
call exit(-1)
endif
! close the file
rc = trexio_close(trex_file)
call trexio_assert(rc, TREXIO_SUCCESS)
@ -365,7 +458,7 @@ subroutine test_read_void(file_name, back_end)
call trexio_assert(rc, TREXIO_OPEN_ERROR)
call trexio_string_of_error(rc, str)
print *, trim(str)
print *, 'Test error message: ', trim(str)
! ================= END OF TEST ===================== !

View File

@ -517,7 +517,7 @@ def get_dtype_dict (dtype: str, target: str, rank = None, int_len_printf = None)
group_dset_format_printf_16 = '"'
group_dset_format_printf_32 = '"'
group_dset_format_scanf = ''
for i in range(rank):
for _ in range(rank):
group_dset_format_printf_8 += item_printf_8
group_dset_format_printf_16 += item_printf_16
group_dset_format_printf_32 += item_printf_32
@ -644,11 +644,16 @@ def split_dset_dict_detailed (datasets: dict) -> tuple:
dset_string_dict = {}
dset_sparse_dict = {}
for k,v in datasets.items():
# create a temp dictionary
tmp_dict = {}
rank = len(v[1])
datatype = v[0]
# skip the data which has 'special' datatype (e.g. determinants for which the code is not templated)
if 'special' in datatype:
continue
# define whether the dset is sparse
is_sparse = False
int_len_printf = {}

View File

@ -635,7 +635,74 @@ prim_factor =
#+end_src
:end:
* TODO Slater determinants
* Slater determinants (determinant group)
The configuration interaction (CI) wave function $\Psi$
can be expanded in the basis of Slater determinants $D_I$ as follows
\[
| \Psi> = \sum_I C_I | D_I> |
\]
For relatively small expansions, a given determinant can be represented as a list of ~mo.num~ occupation numbers.
However, this requires a lot of extra memory and would be technically impossible for larger expansions
(~millions of determinants). This is why the determinants are stored as bit fields in the TREXIO file
(see ~int bitfield~ type in the table below). By default, the chemist notation is used, namely
\[
| 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.
Internally, bit fields for $\alpha$ and $\beta$ electrons are stored separately,
which is why the ~determinant.list~ attribute has a second dimension.
#+NAME: determinant
| Variable | Type | Dimensions | Description |
|---------------+-----------------+-------------------------------+--------------------------------------------------------|
| ~num~ | ~dim~ | | Number of determinants |
| ~list~ | ~int special~ | ~(determinant.num)~ | List of determinants as integer bit fields |
| ~coefficient~ | ~float special~ | ~(state.num,determinant.num)~ | Coefficients of the determinants from the CI expansion |
#+CALL: json(data=determinant, title="determinant")
#+RESULTS:
:RESULTS:
#+begin_src python :tangle trex.json
"determinant": {
"num" : [ "dim" , [] ]
, "list" : [ "int special" , [ "determinant.num" ] ]
, "coefficient" : [ "float special", [ "determinant.num", "state.num" ] ]
} ,
#+end_src
:END:
* Excited states (state group)
By default, the ~determinant~ group corresponds to the ground state.
However, it should be also possible to store the coefficients that
correspond to excited state wave functions for the same set of
determinants. This is the goal of the present group
#+NAME: state
| Variable | Type | Dimensions | Description |
|----------+-------+---------------+------------------------------------------------|
| ~num~ | ~dim~ | | Number of states (including the ground state) |
| ~label~ | ~str~ | ~(state.num)~ | Label of a given state (e.g. 'S' for singlets) |
#+CALL: json(data=state, title="state")
#+RESULTS:
:RESULTS:
#+begin_src python :tangle trex.json
"state": {
"num" : [ "dim", [] ]
, "label" : [ "str", [ "state.num" ] ]
} ,
#+end_src
:END:
* Reduced density matrices (rdm group)
The reduced density matrices are defined in the basis of molecular
@ -724,9 +791,9 @@ prim_factor =
| ~point~ | ~float~ | ~(3, electron.num, qmc.num)~ | 3N-dimensional points |
| ~psi~ | ~float~ | ~(qmc.num)~ | Wave function evaluated at the points |
| ~e_loc~ | ~float~ | ~(qmc.num)~ | Local energy evaluated at the points |
#+CALL: json(data=qmc, title="qmc", last=1)
#+RESULTS:
:results:
#+begin_src python :tangle trex.json