diff --git a/src/templates_front/templator_front.org b/src/templates_front/templator_front.org index 909c27c..134957f 100644 --- a/src/templates_front/templator_front.org +++ b/src/templates_front/templator_front.org @@ -158,44 +158,46 @@ __trexio_path__ = None ** Error handling #+NAME: table-exit-codes - | Macro | Code | Description | - |-------------------------------+------+----------------------------------------| - | ~TREXIO_FAILURE~ | -1 | 'Unknown failure' | - | ~TREXIO_SUCCESS~ | 0 | 'Success' | - | ~TREXIO_INVALID_ARG_1~ | 1 | 'Invalid argument 1' | - | ~TREXIO_INVALID_ARG_2~ | 2 | 'Invalid argument 2' | - | ~TREXIO_INVALID_ARG_3~ | 3 | 'Invalid argument 3' | - | ~TREXIO_INVALID_ARG_4~ | 4 | 'Invalid argument 4' | - | ~TREXIO_INVALID_ARG_5~ | 5 | 'Invalid argument 5' | - | ~TREXIO_END~ | 6 | 'End of file' | - | ~TREXIO_READONLY~ | 7 | 'Read-only file' | - | ~TREXIO_ERRNO~ | 8 | strerror(errno) | - | ~TREXIO_INVALID_ID~ | 9 | 'Invalid ID' | - | ~TREXIO_ALLOCATION_FAILED~ | 10 | 'Allocation failed' | - | ~TREXIO_HAS_NOT~ | 11 | 'Element absent' | - | ~TREXIO_INVALID_NUM~ | 12 | 'Invalid (negative or 0) dimension' | - | ~TREXIO_ATTR_ALREADY_EXISTS~ | 13 | 'Attribute already exists' | - | ~TREXIO_DSET_ALREADY_EXISTS~ | 14 | 'Dataset already exists' | - | ~TREXIO_OPEN_ERROR~ | 15 | 'Error opening file' | - | ~TREXIO_LOCK_ERROR~ | 16 | 'Error locking file' | - | ~TREXIO_UNLOCK_ERROR~ | 17 | 'Error unlocking file' | - | ~TREXIO_FILE_ERROR~ | 18 | 'Invalid file' | - | ~TREXIO_GROUP_READ_ERROR~ | 19 | 'Error reading group' | - | ~TREXIO_GROUP_WRITE_ERROR~ | 20 | 'Error writing group' | - | ~TREXIO_ELEM_READ_ERROR~ | 21 | 'Error reading element' | - | ~TREXIO_ELEM_WRITE_ERROR~ | 22 | 'Error writing element' | - | ~TREXIO_UNSAFE_ARRAY_DIM~ | 23 | 'Access to memory beyond allocated' | - | ~TREXIO_ATTR_MISSING~ | 24 | 'Attribute does not exist in the file' | - | ~TREXIO_DSET_MISSING~ | 25 | 'Dataset does not exist in the file' | - | ~TREXIO_BACK_END_MISSING~ | 26 | 'Requested back end is disabled' | - | ~TREXIO_INVALID_ARG_6~ | 27 | 'Invalid argument 6' | - | ~TREXIO_INVALID_ARG_7~ | 28 | 'Invalid argument 7' | - | ~TREXIO_INVALID_ARG_8~ | 29 | 'Invalid argument 8' | - | ~TREXIO_INVALID_STR_LEN~ | 30 | 'Invalid max_str_len' | - | ~TREXIO_INT_SIZE_OVERFLOW~ | 31 | 'Possible integer overflow' | - | ~TREXIO_SAFE_MODE~ | 32 | 'Unsafe operation in safe mode' | - | ~TREXIO_INVALID_ELECTRON_NUM~ | 33 | 'Inconsistent value of electron num' | - | ~TREXIO_INVALID_STATE~ | 34 | 'Inconsistent state of the file' | + | Macro | Code | Description | + |----------------------------------+------+----------------------------------------| + | ~TREXIO_FAILURE~ | -1 | 'Unknown failure' | + | ~TREXIO_SUCCESS~ | 0 | 'Success' | + | ~TREXIO_INVALID_ARG_1~ | 1 | 'Invalid argument 1' | + | ~TREXIO_INVALID_ARG_2~ | 2 | 'Invalid argument 2' | + | ~TREXIO_INVALID_ARG_3~ | 3 | 'Invalid argument 3' | + | ~TREXIO_INVALID_ARG_4~ | 4 | 'Invalid argument 4' | + | ~TREXIO_INVALID_ARG_5~ | 5 | 'Invalid argument 5' | + | ~TREXIO_END~ | 6 | 'End of file' | + | ~TREXIO_READONLY~ | 7 | 'Read-only file' | + | ~TREXIO_ERRNO~ | 8 | strerror(errno) | + | ~TREXIO_INVALID_ID~ | 9 | 'Invalid ID' | + | ~TREXIO_ALLOCATION_FAILED~ | 10 | 'Allocation failed' | + | ~TREXIO_HAS_NOT~ | 11 | 'Element absent' | + | ~TREXIO_INVALID_NUM~ | 12 | 'Invalid (negative or 0) dimension' | + | ~TREXIO_ATTR_ALREADY_EXISTS~ | 13 | 'Attribute already exists' | + | ~TREXIO_DSET_ALREADY_EXISTS~ | 14 | 'Dataset already exists' | + | ~TREXIO_OPEN_ERROR~ | 15 | 'Error opening file' | + | ~TREXIO_LOCK_ERROR~ | 16 | 'Error locking file' | + | ~TREXIO_UNLOCK_ERROR~ | 17 | 'Error unlocking file' | + | ~TREXIO_FILE_ERROR~ | 18 | 'Invalid file' | + | ~TREXIO_GROUP_READ_ERROR~ | 19 | 'Error reading group' | + | ~TREXIO_GROUP_WRITE_ERROR~ | 20 | 'Error writing group' | + | ~TREXIO_ELEM_READ_ERROR~ | 21 | 'Error reading element' | + | ~TREXIO_ELEM_WRITE_ERROR~ | 22 | 'Error writing element' | + | ~TREXIO_UNSAFE_ARRAY_DIM~ | 23 | 'Access to memory beyond allocated' | + | ~TREXIO_ATTR_MISSING~ | 24 | 'Attribute does not exist in the file' | + | ~TREXIO_DSET_MISSING~ | 25 | 'Dataset does not exist in the file' | + | ~TREXIO_BACK_END_MISSING~ | 26 | 'Requested back end is disabled' | + | ~TREXIO_INVALID_ARG_6~ | 27 | 'Invalid argument 6' | + | ~TREXIO_INVALID_ARG_7~ | 28 | 'Invalid argument 7' | + | ~TREXIO_INVALID_ARG_8~ | 29 | 'Invalid argument 8' | + | ~TREXIO_INVALID_STR_LEN~ | 30 | 'Invalid max_str_len' | + | ~TREXIO_INT_SIZE_OVERFLOW~ | 31 | 'Possible integer overflow' | + | ~TREXIO_SAFE_MODE~ | 32 | 'Unsafe operation in safe mode' | + | ~TREXIO_INVALID_ELECTRON_NUM~ | 33 | 'Inconsistent number of electrons' | + | ~TREXIO_INVALID_DETERMINANT_NUM~ | 34 | 'Inconsistent number of determinants' | + | ~TREXIO_INVALID_STATE~ | 35 | 'Inconsistent state of the file' | + | ~TREXIO_VERSION_PARSING_ISSUE~ | 36 | 'Failed to parse package_version' | # We need to force Emacs not to indent the Python code: # -*- org-src-preserve-indentation: t @@ -276,7 +278,9 @@ return '\n'.join(result) #define TREXIO_INT_SIZE_OVERFLOW ((trexio_exit_code) 31) #define TREXIO_SAFE_MODE ((trexio_exit_code) 32) #define TREXIO_INVALID_ELECTRON_NUM ((trexio_exit_code) 33) - #define TREXIO_INVALID_STATE ((trexio_exit_code) 34) + #define TREXIO_INVALID_DETERMINANT_NUM ((trexio_exit_code) 34) + #define TREXIO_INVALID_STATE ((trexio_exit_code) 35) + #define TREXIO_VERSION_PARSING_ISSUE ((trexio_exit_code) 36) #+end_src #+begin_src f90 :tangle prefix_fortran.f90 :exports none @@ -315,7 +319,9 @@ return '\n'.join(result) integer(trexio_exit_code), parameter :: TREXIO_INT_SIZE_OVERFLOW = 31 integer(trexio_exit_code), parameter :: TREXIO_SAFE_MODE = 32 integer(trexio_exit_code), parameter :: TREXIO_INVALID_ELECTRON_NUM = 33 - integer(trexio_exit_code), parameter :: TREXIO_INVALID_STATE = 34 + integer(trexio_exit_code), parameter :: TREXIO_INVALID_DETERMINANT_NUM = 34 + integer(trexio_exit_code), parameter :: TREXIO_INVALID_STATE = 35 + integer(trexio_exit_code), parameter :: TREXIO_VERSION_PARSING_ISSUE = 36 #+end_src #+begin_src python :tangle prefix_python.py :exports none @@ -355,7 +361,9 @@ return '\n'.join(result) TREXIO_INT_SIZE_OVERFLOW = 31 TREXIO_SAFE_MODE = 32 TREXIO_INVALID_ELECTRON_NUM = 33 - TREXIO_INVALID_STATE = 34 + TREXIO_INVALID_DETERMINANT_NUM = 34 + TREXIO_INVALID_STATE = 35 + TREXIO_VERSION_PARSING_ISSUE = 36 #+end_src :END: @@ -501,11 +509,17 @@ return '\n'.join(result) return "Unsafe operation in safe mode"; break; case TREXIO_INVALID_ELECTRON_NUM: - return "Inconsistent value of electron num"; + return "Inconsistent number of electrons"; + break; + case TREXIO_INVALID_DETERMINANT_NUM: + return "Inconsistent number of determinants"; break; case TREXIO_INVALID_STATE: return "Inconsistent state of the file"; break; + case TREXIO_VERSION_PARSING_ISSUE: + return "Failed to parse package_version"; + break; #+end_example **** C source code @@ -714,6 +728,9 @@ struct trexio_s { char mode; bool one_based; int32_t state; + int16_t version_major; + int16_t version_minor; + int16_t version_patch; char version[16]; }; #+end_src @@ -986,13 +1003,6 @@ trexio_open(const char* file_name, const char mode, return NULL; } - strncpy(result->version, TREXIO_PACKAGE_VERSION, 16); - if (result->version[15] != '\0') { - if (rc_open != NULL) *rc_open = TREXIO_FAILURE; - free(result); - return NULL; - } - result->back_end = back_end_local; result->mode = mode; result->one_based = false; // Need to be flipped in Fortran interface @@ -1081,6 +1091,7 @@ trexio_open(const char* file_name, const char mode, } if (rc == TREXIO_HAS_NOT) { + /* Write TREXIO_PACKAGE_VERSION upon creation of the file */ switch (back_end_local) { case TREXIO_TEXT: @@ -1098,15 +1109,69 @@ trexio_open(const char* file_name, const char mode, #endif } + + if (rc != TREXIO_SUCCESS) { + if (rc_open != NULL) *rc_open = rc; + free(result); + return NULL; + } + + result->version_major = TREXIO_VERSION_MAJOR; + result->version_minor = TREXIO_VERSION_MINOR; + result->version_patch = TREXIO_VERSION_PATCH; + strncpy(result->version, TREXIO_PACKAGE_VERSION, 16); + + } else { + /* Otherwise read the metadata_package_version to get the TREXIO version upon creation of the file */ + char version_origin[16]; + + switch (back_end_local) { + + case TREXIO_TEXT: + rc = trexio_text_read_metadata_package_version(result, version_origin, 16); + break; + + case TREXIO_HDF5: +#ifdef HAVE_HDF5 + rc = trexio_hdf5_read_metadata_package_version(result, version_origin, 16); + break; +#else + if (rc_open != NULL) *rc_open = TREXIO_BACK_END_MISSING; + free(result); + return NULL; +#endif + + } + + if (rc != TREXIO_SUCCESS) { + if (rc_open != NULL) *rc_open = rc; + free(result); + return NULL; + } + + int16_t version_major, version_minor, version_patch; + int rc_scan = sscanf(version_origin, + "%3" SCNd16 ".%5" SCNd16 ".%5" SCNd16, + &version_major, &version_minor, &version_patch); + if (rc_scan != 3) { + if (rc_open != NULL) *rc_open = TREXIO_VERSION_PARSING_ISSUE; + free(result); + return NULL; + } + + result->version_major = version_major; + result->version_minor = version_minor; + result->version_patch = version_patch; + strncpy(result->version, version_origin, 16); + } - if (rc != TREXIO_SUCCESS) { - if (rc_open != NULL) *rc_open = rc; + if (result->version[15] != '\0' || result->version_major == 0) { + if (rc_open != NULL) *rc_open = TREXIO_FAILURE; free(result); return NULL; } - /* Mark the file as unsafe upon opening in UNSAFE 'u' mode */ if (mode == 'u') { @@ -1528,9 +1593,30 @@ trexio_pre_close (trexio_t* file) if (file == NULL) return TREXIO_FILE_ERROR; - /* Up-spin and down-spin electrons */ trexio_exit_code rc; + /* Check consistency between number of determinants and coefficients stored in the file */ + + if (file->version_major >= 2 && file->version_minor >= 2) { + + bool has_det = (trexio_has_determinant_list(file) == TREXIO_SUCCESS); + bool has_coeff = (trexio_has_determinant_coefficient(file) == TREXIO_SUCCESS); + int64_t ndet, ncoeff; + + if (has_det && has_coeff) { + rc = trexio_read_determinant_num_64(file, &ndet); + if (rc != TREXIO_SUCCESS) return rc; + + rc = trexio_read_determinant_coefficient_size(file, &ncoeff); + if (rc != TREXIO_SUCCESS) return rc; + + /* Maybe be even more direct and use assert here so that the user's code crushes in case of inconsistency */ + if (ndet != ncoeff) return TREXIO_INVALID_DETERMINANT_NUM; + } + + } + /* Up-spin and down-spin electrons */ + int32_t nup, ndn, nelec; bool has_up = (trexio_has_electron_up_num(file) == TREXIO_SUCCESS); bool has_dn = (trexio_has_electron_dn_num(file) == TREXIO_SUCCESS);