mirror of
https://github.com/TREX-CoE/qmckl.git
synced 2025-01-03 10:06:09 +01:00
Error handling
This commit is contained in:
parent
6f2adf2921
commit
56f5d9d56d
3
TODO.org
3
TODO.org
@ -16,3 +16,6 @@ context.
|
|||||||
* Complex numbers
|
* Complex numbers
|
||||||
* Adjustable number for derivatives (1,2,3)
|
* Adjustable number for derivatives (1,2,3)
|
||||||
|
|
||||||
|
* Put pictures
|
||||||
|
* Make the Makefile part of the documented code ?
|
||||||
|
* Put the data-flow graph in the code.
|
||||||
|
@ -205,4 +205,3 @@ rm ${nb}.md
|
|||||||
|
|
||||||
* Documentation
|
* Documentation
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
for i in README.org \
|
for i in README.org \
|
||||||
qmckl.org \
|
qmckl.org \
|
||||||
qmckl_memory.org \
|
|
||||||
qmckl_context.org \
|
qmckl_context.org \
|
||||||
|
qmckl_error.org \
|
||||||
|
qmckl_precision.org \
|
||||||
|
qmckl_memory.org \
|
||||||
qmckl_distance.org \
|
qmckl_distance.org \
|
||||||
qmckl_ao.org \
|
qmckl_ao.org \
|
||||||
qmckl_footer.org \
|
qmckl_footer.org \
|
||||||
|
@ -1,18 +1,30 @@
|
|||||||
|
|
||||||
** =qmckl.h= header file
|
** =qmckl.h= header file
|
||||||
|
|
||||||
This file produces the =qmckl.h= header file, which is to be included
|
The =qmckl.h= header file has to be included in <<<C>>> codes when
|
||||||
when qmckl functions are used.
|
QMCkl functions are used:
|
||||||
|
#+BEGIN_SRC C :tangle none
|
||||||
|
#include "qmckl.h"
|
||||||
|
#+END_SRC f90
|
||||||
|
|
||||||
We also create here the =qmckl_f.f90= which is the Fortran interface file.
|
|
||||||
|
In <<<Fortran>>> programs, the =qmckl_f.f90= interface file should be
|
||||||
|
included in the source code using the library, and the Fortran codes
|
||||||
|
should use the ~qmckl~ module as
|
||||||
|
#+BEGIN_SRC f90 :tangle none
|
||||||
|
use qmckl
|
||||||
|
#+END_SRC f90
|
||||||
|
|
||||||
*** Top of header files :noexport:
|
*** Top of header files :noexport:
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl.h
|
#+BEGIN_SRC C :tangle qmckl.h :noweb yes
|
||||||
#ifndef QMCKL_H
|
#ifndef QMCKL_H
|
||||||
#define QMCKL_H
|
#define QMCKL_H
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <math.h>
|
|
||||||
|
<<type-exit-code>>
|
||||||
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+BEGIN_SRC f90 :tangle qmckl_f.f90
|
#+BEGIN_SRC f90 :tangle qmckl_f.f90
|
||||||
@ -22,43 +34,3 @@ module qmckl
|
|||||||
|
|
||||||
The bottoms of the files are located in the [[qmckl_footer.org]] file.
|
The bottoms of the files are located in the [[qmckl_footer.org]] file.
|
||||||
|
|
||||||
*** Constants
|
|
||||||
|
|
||||||
**** Success/failure
|
|
||||||
|
|
||||||
These are the codes returned by the functions to indicate success
|
|
||||||
or failure. All such functions should have as a return type =qmckl_exit_code=.
|
|
||||||
|
|
||||||
#+BEGIN_SRC C :comments org :tangle qmckl.h
|
|
||||||
#define QMCKL_SUCCESS 0
|
|
||||||
#define QMCKL_FAILURE 1
|
|
||||||
|
|
||||||
typedef int32_t qmckl_exit_code;
|
|
||||||
typedef int64_t qmckl_context ;
|
|
||||||
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
#+BEGIN_SRC f90 :comments org :tangle qmckl_f.f90
|
|
||||||
integer, parameter :: QMCKL_SUCCESS = 0
|
|
||||||
integer, parameter :: QMCKL_FAILURE = 0
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
**** Precision-related constants
|
|
||||||
|
|
||||||
Controlling numerical precision enables optimizations. Here, the
|
|
||||||
default parameters determining the target numerical precision and
|
|
||||||
range are defined.
|
|
||||||
|
|
||||||
#+BEGIN_SRC C :comments org :tangle qmckl.h
|
|
||||||
#define QMCKL_DEFAULT_PRECISION 53
|
|
||||||
#define QMCKL_DEFAULT_RANGE 11
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
#+BEGIN_SRC f90 :comments org :tangle qmckl_f.f90
|
|
||||||
integer, parameter :: QMCKL_DEFAULT_PRECISION = 53
|
|
||||||
integer, parameter :: QMCKL_DEFAULT_RANGE = 11
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
|
|
||||||
# -*- mode: org -*-
|
|
||||||
# vim: syntax=c
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
:h: qmckl.h
|
:h: qmckl.h
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
|
|
||||||
This file is written in C because it is more natural to express the
|
This file is written in C because it is more natural to express the
|
||||||
context in C than in Fortran.
|
context in C than in Fortran.
|
||||||
|
|
||||||
@ -17,6 +16,9 @@
|
|||||||
*** Headers :noexport:
|
*** Headers :noexport:
|
||||||
#+BEGIN_SRC C :tangle (org-entry-get nil "c" t)
|
#+BEGIN_SRC C :tangle (org-entry-get nil "c" t)
|
||||||
#include "qmckl.h"
|
#include "qmckl.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle (org-entry-get nil "c_test" t)
|
#+BEGIN_SRC C :tangle (org-entry-get nil "c_test" t)
|
||||||
@ -27,25 +29,42 @@ MunitResult test_qmckl_context() {
|
|||||||
|
|
||||||
*** Context
|
*** Context
|
||||||
|
|
||||||
The context variable is a handle for the state of the library, and
|
The <<<context>>> variable is a handle for the state of the library, and
|
||||||
is stored in the following data structure, which can't be seen
|
is stored in the following data structure, which can't be seen
|
||||||
outside of the library. To simplify compatibility with other
|
outside of the library. To simplify compatibility with other
|
||||||
languages, the pointer to the internal data structure is converted
|
languages, the pointer to the internal data structure is converted
|
||||||
into a 64-bit signed integer, defined in the ~qmckl_context~ type.
|
into a 64-bit signed integer, defined in the ~qmckl_context~ type.
|
||||||
A value of 0 for the context is equivalent to a ~NULL~ pointer.
|
A value of ~0~ for the context is equivalent to a ~NULL~ pointer.
|
||||||
|
|
||||||
# The following code block should be kept to insert comments into
|
#+BEGIN_SRC C :comments org :tangle qmckl.h
|
||||||
# the qmckl.h file
|
typedef int64_t qmckl_context ;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
**** Data for error handling
|
||||||
|
|
||||||
|
We define here the the data structure containing the strings
|
||||||
|
necessary for error handling.
|
||||||
|
|
||||||
|
#+BEGIN_SRC C :comments org :tangle qmckl.h
|
||||||
|
#define QMCKL_MAX_FUN_LEN 256
|
||||||
|
#define QMCKL_MAX_MSG_LEN 1024
|
||||||
|
|
||||||
|
typedef struct qmckl_error_struct {
|
||||||
|
|
||||||
|
qmckl_exit_code exit_code;
|
||||||
|
char function[QMCKL_MAX_FUN_LEN];
|
||||||
|
char message [QMCKL_MAX_MSG_LEN];
|
||||||
|
|
||||||
|
} qmckl_error_struct;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
#+BEGIN_SRC C :comments org :tangle (org-entry-get nil "h" t) :export none
|
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
**** Basis set data structure
|
**** Basis set data structure
|
||||||
|
|
||||||
Data structure for the info related to the atomic orbitals
|
Data structure for the info related to the atomic orbitals
|
||||||
basis set.
|
basis set.
|
||||||
|
|
||||||
#+BEGIN_SRC C :comments org :tangle (org-entry-get nil "c" t)
|
#+BEGIN_SRC C :comments org :tangle (org-entry-get nil "h" t)
|
||||||
typedef struct qmckl_ao_basis_struct {
|
typedef struct qmckl_ao_basis_struct {
|
||||||
|
|
||||||
int64_t shell_num;
|
int64_t shell_num;
|
||||||
@ -61,12 +80,12 @@ typedef struct qmckl_ao_basis_struct {
|
|||||||
} qmckl_ao_basis_struct;
|
} qmckl_ao_basis_struct;
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
**** Source
|
***** Source
|
||||||
|
|
||||||
The tag is used internally to check if the memory domain pointed
|
The tag is used internally to check if the memory domain pointed
|
||||||
by a pointer is a valid context.
|
by a pointer is a valid context.
|
||||||
|
|
||||||
#+BEGIN_SRC C :comments org :tangle (org-entry-get nil "c" t)
|
#+BEGIN_SRC C :comments org :tangle (org-entry-get nil "h" t)
|
||||||
typedef struct qmckl_context_struct {
|
typedef struct qmckl_context_struct {
|
||||||
|
|
||||||
struct qmckl_context_struct * prev;
|
struct qmckl_context_struct * prev;
|
||||||
@ -83,17 +102,92 @@ typedef struct qmckl_context_struct {
|
|||||||
int32_t precision;
|
int32_t precision;
|
||||||
int32_t range;
|
int32_t range;
|
||||||
|
|
||||||
|
/* Error handling */
|
||||||
|
struct qmckl_error_struct * error;
|
||||||
|
|
||||||
} qmckl_context_struct;
|
} qmckl_context_struct;
|
||||||
|
|
||||||
#define VALID_TAG 0xBEEFFACE
|
#define VALID_TAG 0xBEEFFACE
|
||||||
#define INVALID_TAG 0xDEADBEEF
|
#define INVALID_TAG 0xDEADBEEF
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
**** ~qmckl_context_update_error~
|
||||||
|
|
||||||
|
#+BEGIN_SRC C :comments org :tangle (org-entry-get nil "h" t)
|
||||||
|
qmckl_exit_code
|
||||||
|
qmckl_context_update_error(qmckl_context context, const qmckl_exit_code exit_code, const char* function, const char* message);
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
**** Test :noexport:
|
***** Source
|
||||||
#+BEGIN_SRC C :tangle (org-entry-get nil "c_test" t)
|
#+BEGIN_SRC C :tangle (org-entry-get nil "c" t)
|
||||||
|
qmckl_exit_code
|
||||||
|
qmckl_context_update_error(qmckl_context context, const qmckl_exit_code exit_code, const char* function, const char* message)
|
||||||
|
{
|
||||||
|
assert (context != 0);
|
||||||
|
assert (function != NULL);
|
||||||
|
assert (message != NULL);
|
||||||
|
assert (exit_code > 0);
|
||||||
|
assert (exit_code < QMCKL_INVALID_EXIT_CODE);
|
||||||
|
|
||||||
|
qmckl_context_struct* ctx = (qmckl_context_struct*) context;
|
||||||
|
if (ctx == NULL) return QMCKL_FAILURE;
|
||||||
|
|
||||||
|
if (ctx->error != NULL) {
|
||||||
|
free(ctx->error);
|
||||||
|
ctx->error = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qmckl_error_struct* error = (qmckl_error_struct*) qmckl_malloc (context, sizeof(qmckl_error_struct));
|
||||||
|
error->exit_code = exit_code;
|
||||||
|
strcpy(error->function, function);
|
||||||
|
strcpy(error->message, message);
|
||||||
|
|
||||||
|
ctx->error = error;
|
||||||
|
|
||||||
|
return QMCKL_SUCCESS;
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
***** TODO Test
|
||||||
|
|
||||||
|
**** ~qmckl_context_set_error~
|
||||||
|
|
||||||
|
#+BEGIN_SRC C :comments org :tangle (org-entry-get nil "h" t)
|
||||||
|
qmckl_context
|
||||||
|
qmckl_context_set_error(qmckl_context context, const qmckl_exit_code exit_code, const char* function, const char* message);
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
***** Source
|
||||||
|
#+BEGIN_SRC C :tangle (org-entry-get nil "c" t)
|
||||||
|
qmckl_context
|
||||||
|
qmckl_context_set_error(qmckl_context context, const qmckl_exit_code exit_code, const char* function, const char* message)
|
||||||
|
{
|
||||||
|
assert (context != 0);
|
||||||
|
assert (function != NULL);
|
||||||
|
assert (message != NULL);
|
||||||
|
assert (exit_code > 0);
|
||||||
|
assert (exit_code < QMCKL_INVALID_EXIT_CODE);
|
||||||
|
|
||||||
|
qmckl_context new_context = qmckl_context_copy(context);
|
||||||
|
if (new_context == 0) return context;
|
||||||
|
|
||||||
|
if (qmckl_context_update_error(new_context, exit_code,
|
||||||
|
function, message) != QMCKL_SUCCESS) {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_context;
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
***** TODO Test
|
||||||
|
|
||||||
|
***** Test :noexport:
|
||||||
|
|
||||||
|
#+BEGIN_SRC C :tangle (org-entry-get nil "c_test" t)
|
||||||
qmckl_context context;
|
qmckl_context context;
|
||||||
qmckl_context new_context;
|
qmckl_context new_context;
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
**** ~qmckl_context_check~
|
**** ~qmckl_context_check~
|
||||||
@ -145,6 +239,7 @@ qmckl_context qmckl_context_create() {
|
|||||||
context->precision = QMCKL_DEFAULT_PRECISION;
|
context->precision = QMCKL_DEFAULT_PRECISION;
|
||||||
context->range = QMCKL_DEFAULT_RANGE;
|
context->range = QMCKL_DEFAULT_RANGE;
|
||||||
context->tag = VALID_TAG;
|
context->tag = VALID_TAG;
|
||||||
|
context->error = NULL;
|
||||||
|
|
||||||
return (qmckl_context) context;
|
return (qmckl_context) context;
|
||||||
}
|
}
|
||||||
@ -201,6 +296,7 @@ qmckl_context qmckl_context_copy(const qmckl_context context) {
|
|||||||
new_context->precision = old_context->precision;
|
new_context->precision = old_context->precision;
|
||||||
new_context->range = old_context->range;
|
new_context->range = old_context->range;
|
||||||
new_context->tag = VALID_TAG;
|
new_context->tag = VALID_TAG;
|
||||||
|
new_context->error = old_context->error;
|
||||||
|
|
||||||
return (qmckl_context) new_context;
|
return (qmckl_context) new_context;
|
||||||
}
|
}
|
||||||
@ -291,8 +387,7 @@ qmckl_exit_code qmckl_context_destroy(const qmckl_context context) {
|
|||||||
if (ctx == NULL) return QMCKL_FAILURE;
|
if (ctx == NULL) return QMCKL_FAILURE;
|
||||||
|
|
||||||
ctx->tag = INVALID_TAG;
|
ctx->tag = INVALID_TAG;
|
||||||
qmckl_free(ctx);
|
return qmckl_free(context,ctx);
|
||||||
return QMCKL_SUCCESS;
|
|
||||||
}
|
}
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
@ -316,11 +411,11 @@ munit_assert_int64(qmckl_context_check(new_context), ==, (qmckl_context) 0);
|
|||||||
munit_assert_int64(qmckl_context_destroy((qmckl_context) 0), ==, QMCKL_FAILURE);
|
munit_assert_int64(qmckl_context_destroy((qmckl_context) 0), ==, QMCKL_FAILURE);
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
*** Basis set
|
**** Basis set
|
||||||
|
|
||||||
For H_2 with the following basis set,
|
For H_2 with the following basis set,
|
||||||
|
|
||||||
#+BEGIN_EXAMPLE
|
#+BEGIN_EXAMPLE
|
||||||
HYDROGEN
|
HYDROGEN
|
||||||
S 5
|
S 5
|
||||||
1 3.387000E+01 6.068000E-03
|
1 3.387000E+01 6.068000E-03
|
||||||
@ -338,11 +433,11 @@ P 1
|
|||||||
1 3.880000E-01 1.000000E+00
|
1 3.880000E-01 1.000000E+00
|
||||||
D 1
|
D 1
|
||||||
1 1.057000E+00 1.0000000
|
1 1.057000E+00 1.0000000
|
||||||
#+END_EXAMPLE
|
#+END_EXAMPLE
|
||||||
|
|
||||||
we have:
|
we have:
|
||||||
|
|
||||||
#+BEGIN_EXAMPLE
|
#+BEGIN_EXAMPLE
|
||||||
type = 'G'
|
type = 'G'
|
||||||
shell_num = 12
|
shell_num = 12
|
||||||
prim_num = 20
|
prim_num = 20
|
||||||
@ -356,7 +451,7 @@ EXPONENT = [ 33.87, 5.095, 1.159, 0.3258, 0.1027, 0.3258, 0.1027,
|
|||||||
COEFFICIENT = [ 0.006068, 0.045308, 0.202822, 0.503903, 0.383421,
|
COEFFICIENT = [ 0.006068, 0.045308, 0.202822, 0.503903, 0.383421,
|
||||||
1.0, 1.0, 1.0, 1.0, 1.0, 0.006068, 0.045308, 0.202822,
|
1.0, 1.0, 1.0, 1.0, 1.0, 0.006068, 0.045308, 0.202822,
|
||||||
0.503903, 0.383421, 1.0, 1.0, 1.0, 1.0, 1.0]
|
0.503903, 0.383421, 1.0, 1.0, 1.0, 1.0, 1.0]
|
||||||
#+END_EXAMPLE
|
#+END_EXAMPLE
|
||||||
|
|
||||||
**** ~qmckl_context_update_ao_basis~
|
**** ~qmckl_context_update_ao_basis~
|
||||||
|
|
||||||
@ -425,52 +520,52 @@ qmckl_context_update_ao_basis(qmckl_context context , const char type
|
|||||||
|
|
||||||
basis->shell_center = (int64_t*) malloc (shell_num * sizeof(int64_t));
|
basis->shell_center = (int64_t*) malloc (shell_num * sizeof(int64_t));
|
||||||
if (basis->shell_center == NULL) {
|
if (basis->shell_center == NULL) {
|
||||||
free(basis);
|
qmckl_free(context, basis);
|
||||||
return QMCKL_FAILURE;
|
return QMCKL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
basis->shell_ang_mom = (int32_t*) malloc (shell_num * sizeof(int32_t));
|
basis->shell_ang_mom = (int32_t*) malloc (shell_num * sizeof(int32_t));
|
||||||
if (basis->shell_ang_mom == NULL) {
|
if (basis->shell_ang_mom == NULL) {
|
||||||
free(basis->shell_center);
|
qmckl_free(context, basis->shell_center);
|
||||||
free(basis);
|
qmckl_free(context, basis);
|
||||||
return QMCKL_FAILURE;
|
return QMCKL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
basis->shell_prim_num= (int64_t*) malloc (shell_num * sizeof(int64_t));
|
basis->shell_prim_num= (int64_t*) malloc (shell_num * sizeof(int64_t));
|
||||||
if (basis->shell_prim_num == NULL) {
|
if (basis->shell_prim_num == NULL) {
|
||||||
free(basis->shell_ang_mom);
|
qmckl_free(context, basis->shell_ang_mom);
|
||||||
free(basis->shell_center);
|
qmckl_free(context, basis->shell_center);
|
||||||
free(basis);
|
qmckl_free(context, basis);
|
||||||
return QMCKL_FAILURE;
|
return QMCKL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
basis->shell_factor = (double *) malloc (shell_num * sizeof(double ));
|
basis->shell_factor = (double *) malloc (shell_num * sizeof(double ));
|
||||||
if (basis->shell_factor == NULL) {
|
if (basis->shell_factor == NULL) {
|
||||||
free(basis->shell_prim_num);
|
qmckl_free(context, basis->shell_prim_num);
|
||||||
free(basis->shell_ang_mom);
|
qmckl_free(context, basis->shell_ang_mom);
|
||||||
free(basis->shell_center);
|
qmckl_free(context, basis->shell_center);
|
||||||
free(basis);
|
qmckl_free(context, basis);
|
||||||
return QMCKL_FAILURE;
|
return QMCKL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
basis->exponent = (double *) malloc (prim_num * sizeof(double ));
|
basis->exponent = (double *) malloc (prim_num * sizeof(double ));
|
||||||
if (basis->exponent == NULL) {
|
if (basis->exponent == NULL) {
|
||||||
free(basis->shell_factor);
|
qmckl_free(context, basis->shell_factor);
|
||||||
free(basis->shell_prim_num);
|
qmckl_free(context, basis->shell_prim_num);
|
||||||
free(basis->shell_ang_mom);
|
qmckl_free(context, basis->shell_ang_mom);
|
||||||
free(basis->shell_center);
|
qmckl_free(context, basis->shell_center);
|
||||||
free(basis);
|
qmckl_free(context, basis);
|
||||||
return QMCKL_FAILURE;
|
return QMCKL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
basis->coefficient = (double *) malloc (prim_num * sizeof(double ));
|
basis->coefficient = (double *) malloc (prim_num * sizeof(double ));
|
||||||
if (basis->coefficient == NULL) {
|
if (basis->coefficient == NULL) {
|
||||||
free(basis->exponent);
|
qmckl_free(context, basis->exponent);
|
||||||
free(basis->shell_factor);
|
qmckl_free(context, basis->shell_factor);
|
||||||
free(basis->shell_prim_num);
|
qmckl_free(context, basis->shell_prim_num);
|
||||||
free(basis->shell_ang_mom);
|
qmckl_free(context, basis->shell_ang_mom);
|
||||||
free(basis->shell_center);
|
qmckl_free(context, basis->shell_center);
|
||||||
free(basis);
|
qmckl_free(context, basis);
|
||||||
return QMCKL_FAILURE;
|
return QMCKL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,7 +656,7 @@ qmckl_context_set_ao_basis(const qmckl_context context , const char typ
|
|||||||
qmckl_context new_context = qmckl_context_copy(context);
|
qmckl_context new_context = qmckl_context_copy(context);
|
||||||
if (new_context == 0) return 0;
|
if (new_context == 0) return 0;
|
||||||
|
|
||||||
if (qmckl_context_update_ao_basis(context, type, shell_num, prim_num,
|
if (qmckl_context_update_ao_basis(new_context, type, shell_num, prim_num,
|
||||||
SHELL_CENTER, SHELL_ANG_MOM, SHELL_FACTOR,
|
SHELL_CENTER, SHELL_ANG_MOM, SHELL_FACTOR,
|
||||||
SHELL_PRIM_NUM, SHELL_PRIM_INDEX, EXPONENT,
|
SHELL_PRIM_NUM, SHELL_PRIM_INDEX, EXPONENT,
|
||||||
COEFFICIENT
|
COEFFICIENT
|
||||||
@ -596,16 +691,16 @@ qmckl_context_set_ao_basis(const qmckl_context context , const char typ
|
|||||||
|
|
||||||
***** TODO Test
|
***** TODO Test
|
||||||
|
|
||||||
*** Precision
|
**** Precision
|
||||||
|
|
||||||
The following functions set and get the expected required
|
The following functions set and get the expected required
|
||||||
precision and range. ~precision~ should be an integer between 2
|
precision and range. ~precision~ should be an integer between 2
|
||||||
and 53, and ~range~ should be an integer between 2 and 11.
|
and 53, and ~range~ should be an integer between 2 and 11.
|
||||||
|
|
||||||
The setter functions functions return a new context as a 64-bit
|
The setter functions functions return a new context as a 64-bit
|
||||||
integer. The getter functions return the value, as a 32-bit
|
integer. The getter functions return the value, as a 32-bit
|
||||||
integer. The update functions return ~QMCKL_SUCCESS~ or
|
integer. The update functions return ~QMCKL_SUCCESS~ or
|
||||||
~QMCKL_FAILURE~.
|
~QMCKL_FAILURE~.
|
||||||
|
|
||||||
**** ~qmckl_context_update_precision~
|
**** ~qmckl_context_update_precision~
|
||||||
Modifies the parameter for the numerical precision in a given context.
|
Modifies the parameter for the numerical precision in a given context.
|
||||||
@ -685,7 +780,7 @@ qmckl_context qmckl_context_set_precision(const qmckl_context context, const int
|
|||||||
qmckl_context new_context = qmckl_context_copy(context);
|
qmckl_context new_context = qmckl_context_copy(context);
|
||||||
if (new_context == 0) return 0;
|
if (new_context == 0) return 0;
|
||||||
|
|
||||||
if (qmckl_context_update_precision(context, precision) == QMCKL_FAILURE) return 0;
|
if (qmckl_context_update_precision(new_context, precision) == QMCKL_FAILURE) return 0;
|
||||||
|
|
||||||
return new_context;
|
return new_context;
|
||||||
}
|
}
|
||||||
@ -715,7 +810,7 @@ qmckl_context qmckl_context_set_range(const qmckl_context context, const int ran
|
|||||||
qmckl_context new_context = qmckl_context_copy(context);
|
qmckl_context new_context = qmckl_context_copy(context);
|
||||||
if (new_context == 0) return 0;
|
if (new_context == 0) return 0;
|
||||||
|
|
||||||
if (qmckl_context_update_range(context, range) == QMCKL_FAILURE) return 0;
|
if (qmckl_context_update_range(new_context, range) == QMCKL_FAILURE) return 0;
|
||||||
|
|
||||||
return new_context;
|
return new_context;
|
||||||
}
|
}
|
||||||
|
193
src/qmckl_error.org
Normal file
193
src/qmckl_error.org
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
# This file is part of the qmckl.h file
|
||||||
|
** Error handling
|
||||||
|
:PROPERTIES:
|
||||||
|
:c: qmckl_error.c
|
||||||
|
:c_test: test_qmckl_error.c
|
||||||
|
:fh: qmckl_f.f90
|
||||||
|
:h: qmckl.h
|
||||||
|
:END:
|
||||||
|
|
||||||
|
This file is written in C because it is more natural to express the
|
||||||
|
error handling in C than in Fortran.
|
||||||
|
|
||||||
|
2 files are produced:
|
||||||
|
- a source file : =qmckl_error.c=
|
||||||
|
- a test file : =test_qmckl_error.c=
|
||||||
|
|
||||||
|
*** Headers :noexport:
|
||||||
|
#+BEGIN_SRC C :tangle (org-entry-get nil "c" t)
|
||||||
|
#include "qmckl.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC C :tangle (org-entry-get nil "c_test" t)
|
||||||
|
#include "qmckl.h"
|
||||||
|
#include "munit.h"
|
||||||
|
MunitResult test_qmckl_error() {
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Error handling
|
||||||
|
|
||||||
|
The library should never make the calling programs abort, nor
|
||||||
|
perform any input/output operations. This decision has to be taken
|
||||||
|
by the developer of the code calling the library.
|
||||||
|
|
||||||
|
All the functions return with an <<<exit code>>>, defined as
|
||||||
|
#+NAME: type-exit-code
|
||||||
|
#+BEGIN_SRC C :comments org :tangle qmckl.h
|
||||||
|
typedef int32_t qmckl_exit_code;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
The exit code returns the completion status of the function to the
|
||||||
|
calling program. When a function call completed successfully, the
|
||||||
|
~QMCKL_SUCCESS~ exit code is returned. If one of the functions of
|
||||||
|
the library fails to complete the requested task, an appropriate
|
||||||
|
error code is returned to the program.
|
||||||
|
|
||||||
|
Here is the complete list of exit codes.
|
||||||
|
|
||||||
|
#+NAME: table-exit-codes
|
||||||
|
| ~QMCKL_SUCCESS~ | 0 |
|
||||||
|
| ~QMCKL_INVALID_ARG_1~ | 1 |
|
||||||
|
| ~QMCKL_INVALID_ARG_2~ | 2 |
|
||||||
|
| ~QMCKL_INVALID_ARG_3~ | 3 |
|
||||||
|
| ~QMCKL_INVALID_ARG_4~ | 4 |
|
||||||
|
| ~QMCKL_INVALID_ARG_5~ | 5 |
|
||||||
|
| ~QMCKL_INVALID_ARG_6~ | 6 |
|
||||||
|
| ~QMCKL_INVALID_ARG_7~ | 7 |
|
||||||
|
| ~QMCKL_INVALID_ARG_8~ | 8 |
|
||||||
|
| ~QMCKL_INVALID_ARG_9~ | 9 |
|
||||||
|
| ~QMCKL_INVALID_ARG_10~ | 10 |
|
||||||
|
| ~QMCKL_NULL_CONTEXT~ | 101 |
|
||||||
|
| ~QMCKL_FAILURE~ | 102 |
|
||||||
|
| ~QMCKL_ERRNO~ | 103 |
|
||||||
|
| ~QMCKL_INVALID_EXIT_CODE~ | 104 |
|
||||||
|
|
||||||
|
# We need to force Emacs not to indent the Python code:
|
||||||
|
# -*- org-src-preserve-indentation: t
|
||||||
|
#+BEGIN_SRC python :var table=table-exit-codes :results drawer :exports result
|
||||||
|
""" This script generates the C and Fortran constants for the error
|
||||||
|
codes from the org-mode table.
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = [ "#+BEGIN_SRC C :comments org :tangle qmckl.h" ]
|
||||||
|
for (text, code) in table:
|
||||||
|
text=text.replace("~","")
|
||||||
|
result += [ f"#define {text:30s} {code:d}" ]
|
||||||
|
result += [ "#+END_SRC" ]
|
||||||
|
|
||||||
|
result += [ "" ]
|
||||||
|
|
||||||
|
result += [ "#+BEGIN_SRC f90 :comments org :tangle qmckl_f.f90" ]
|
||||||
|
for (text, code) in table:
|
||||||
|
text=text.replace("~","")
|
||||||
|
result += [ f" integer, parameter :: {text:30s} = {code:d}" ]
|
||||||
|
result += [ "#+END_SRC" ]
|
||||||
|
|
||||||
|
return '\n'.join(result)
|
||||||
|
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
:results:
|
||||||
|
#+BEGIN_SRC C :comments org :tangle qmckl.h
|
||||||
|
#define QMCKL_SUCCESS 0
|
||||||
|
#define QMCKL_INVALID_ARG_1 1
|
||||||
|
#define QMCKL_INVALID_ARG_2 2
|
||||||
|
#define QMCKL_INVALID_ARG_3 3
|
||||||
|
#define QMCKL_INVALID_ARG_4 4
|
||||||
|
#define QMCKL_INVALID_ARG_5 5
|
||||||
|
#define QMCKL_INVALID_ARG_6 6
|
||||||
|
#define QMCKL_INVALID_ARG_7 7
|
||||||
|
#define QMCKL_INVALID_ARG_8 8
|
||||||
|
#define QMCKL_INVALID_ARG_9 9
|
||||||
|
#define QMCKL_INVALID_ARG_10 10
|
||||||
|
#define QMCKL_NULL_CONTEXT 101
|
||||||
|
#define QMCKL_FAILURE 102
|
||||||
|
#define QMCKL_ERRNO 103
|
||||||
|
#define QMCKL_INVALID_EXIT_CODE 104
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC f90 :comments org :tangle qmckl_f.f90
|
||||||
|
integer, parameter :: QMCKL_SUCCESS = 0
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_1 = 1
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_2 = 2
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_3 = 3
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_4 = 4
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_5 = 5
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_6 = 6
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_7 = 7
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_8 = 8
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_9 = 9
|
||||||
|
integer, parameter :: QMCKL_INVALID_ARG_10 = 10
|
||||||
|
integer, parameter :: QMCKL_NULL_CONTEXT = 101
|
||||||
|
integer, parameter :: QMCKL_FAILURE = 102
|
||||||
|
integer, parameter :: QMCKL_ERRNO = 103
|
||||||
|
integer, parameter :: QMCKL_INVALID_EXIT_CODE = 104
|
||||||
|
#+END_SRC
|
||||||
|
:end:
|
||||||
|
|
||||||
|
To make a function fail, the <<<~qmckl_failwith~>>> function should be
|
||||||
|
called, such that information about the failure is stored in
|
||||||
|
the context. The desired exit code is given as an argument, as
|
||||||
|
well as the name of the function and an error message. The return
|
||||||
|
code of the function is the desired return code.
|
||||||
|
|
||||||
|
#+BEGIN_SRC C :comments org :tangle qmckl.h
|
||||||
|
qmckl_exit_code qmckl_failwith(qmckl_context context,
|
||||||
|
const qmckl_exit_code exit_code,
|
||||||
|
const char* function,
|
||||||
|
const char* message) ;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC C :comments org :tangle qmckl_error.c
|
||||||
|
qmckl_exit_code qmckl_failwith(qmckl_context context,
|
||||||
|
const qmckl_exit_code exit_code,
|
||||||
|
const char* function,
|
||||||
|
const char* message) {
|
||||||
|
if (context == 0) return QMCKL_NULL_CONTEXT;
|
||||||
|
assert (exit_code > 0);
|
||||||
|
assert (exit_code < QMCKL_INVALID_EXIT_CODE);
|
||||||
|
assert (function != NULL);
|
||||||
|
assert (message != NULL);
|
||||||
|
assert (strlen(function) < QMCKL_MAX_FUN_LEN);
|
||||||
|
assert (strlen(message) < QMCKL_MAX_MSG_LEN);
|
||||||
|
|
||||||
|
context = qmckl_context_set_error(context, exit_code, function, message);
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
For example, this function can be used as
|
||||||
|
#+BEGIN_SRC C :tangle no
|
||||||
|
if (x < 0) {
|
||||||
|
return qmckl_failwith(context,
|
||||||
|
QMCKL_INVALID_ARG_2,
|
||||||
|
"qmckl_function",
|
||||||
|
"Expected x >= 0");
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
|
# To decode the error messages, the <<<~qmckl_strerror~>>> converts an
|
||||||
|
# error code into a string.
|
||||||
|
|
||||||
|
*** End of files :noexport:
|
||||||
|
|
||||||
|
***** Test
|
||||||
|
#+BEGIN_SRC C :comments link :tangle (org-entry-get nil "c_test" t)
|
||||||
|
return MUNIT_OK;
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# -*- mode: org -*-
|
||||||
|
# vim: syntax=c
|
||||||
|
|
||||||
|
# -*- mode: org -*-
|
||||||
|
# vim: syntax=c
|
@ -67,33 +67,39 @@ munit_assert_int(a[2], ==, 3);
|
|||||||
|
|
||||||
*** ~qmckl_free~
|
*** ~qmckl_free~
|
||||||
|
|
||||||
|
The context is passed, in case some important information has been
|
||||||
|
stored related to memory allocation and needs to be updated.
|
||||||
|
|
||||||
#+BEGIN_SRC C :tangle qmckl.h
|
#+BEGIN_SRC C :tangle qmckl.h
|
||||||
void* qmckl_free(void *ptr);
|
qmckl_exit_code qmckl_free(qmckl_context context, void *ptr);
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+BEGIN_SRC f90 :tangle qmckl_f.f90
|
#+BEGIN_SRC f90 :tangle qmckl_f.f90
|
||||||
interface
|
interface
|
||||||
type (c_ptr) function qmckl_free (ptr) bind(C)
|
integer (c_int32_t) function qmckl_free (context, ptr) bind(C)
|
||||||
use, intrinsic :: iso_c_binding
|
use, intrinsic :: iso_c_binding
|
||||||
|
integer (c_int64_t), intent(in), value :: context
|
||||||
type (c_ptr), intent(in), value :: ptr
|
type (c_ptr), intent(in), value :: ptr
|
||||||
end function qmckl_free
|
end function qmckl_free
|
||||||
end interface
|
end interface
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
**** Source
|
**** Source
|
||||||
#+BEGIN_SRC C :tangle qmckl_memory.c
|
#+BEGIN_SRC C :tangle qmckl_memory.c
|
||||||
void* qmckl_free(void *ptr) {
|
qmckl_exit_code qmckl_free(qmckl_context context, void *ptr) {
|
||||||
assert (ptr != NULL);
|
if (context == 0) return QMCKL_INVALID_ARG_1;
|
||||||
|
if (ptr == NULL) return QMCKL_INVALID_ARG_2;
|
||||||
free(ptr);
|
free(ptr);
|
||||||
return NULL;
|
return QMCKL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
**** Test :noexport:
|
**** Test :noexport:
|
||||||
#+BEGIN_SRC C :tangle test_qmckl_memory.c
|
#+BEGIN_SRC C :tangle test_qmckl_memory.c
|
||||||
munit_assert(a != NULL);
|
munit_assert(a != NULL);
|
||||||
a = qmckl_free(a);
|
qmckl_exit_code rc;
|
||||||
munit_assert(a == NULL);
|
rc = qmckl_free( (qmckl_context) 1, a);
|
||||||
|
munit_assert(rc == QMCKL_SUCCESS);
|
||||||
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
21
src/qmckl_precision.org
Normal file
21
src/qmckl_precision.org
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# This file is part of the qmckl.h file
|
||||||
|
|
||||||
|
*** Multi-precision related constants
|
||||||
|
|
||||||
|
Controlling numerical precision enables optimizations. Here, the
|
||||||
|
default parameters determining the target numerical precision and
|
||||||
|
range are defined.
|
||||||
|
|
||||||
|
#+BEGIN_SRC C :comments org :tangle qmckl.h
|
||||||
|
#define QMCKL_DEFAULT_PRECISION 53
|
||||||
|
#define QMCKL_DEFAULT_RANGE 11
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC f90 :comments org :tangle qmckl_f.f90
|
||||||
|
integer, parameter :: QMCKL_DEFAULT_PRECISION = 53
|
||||||
|
integer, parameter :: QMCKL_DEFAULT_RANGE = 11
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
|
# -*- mode: org -*-
|
||||||
|
# vim: syntax=c
|
Loading…
Reference in New Issue
Block a user