Table of Contents
+ ++#i+TITLE: Nucleus +
+ ++A ll the data relative to the molecular geometry is described here. +
+ +1 Context
++The following data stored in the context: +
+ +uninitialized |
+int32t | +Keeps bit set for uninitialized data | +
num |
+int64t | +Total number of nuclei | +
provided |
+bool | +If true, nucleus is valid |
+
charge |
+double[num] | +Nuclear charges | +
coord |
+double[3][num] | +Nuclear coordinates | +
nn_distance |
+double[num][num] | +Nucleus-nucleus distances | +
nn_distance_date |
+int64t | +Date when Nucleus-nucleus distances were computed | +
repulsion |
+double | +Nuclear repulsion energy | +
repulsion_date |
+int64t | +Date when the nuclear repulsion energy was computed | +
1.1 Data structure
+typedef struct qmckl_nucleus_struct { + int64_t num; + int64_t repulsion_date; + int64_t nn_distance_date; + double* coord; + double* charge; + double* nn_distance; + double repulsion; + int32_t uninitialized; + bool provided; +} qmckl_nucleus_struct; ++
+The uninitialized
integer contains one bit set to one for each
+initialization function which has not bee called. It becomes equal
+to zero after all initialization functions have been called. The
+struct is then initialized and provided == true
.
+
1.2 Access functions
+
+When all the data relative to nuclei have been set, the following
+function returns true
.
+
bool qmckl_nucleus_provided (const qmckl_context context); ++
1.3 Initialization functions
++To set the data relative to the nuclei in the context, the +following functions need to be called. +
+ +qmckl_exit_code qmckl_set_nucleus_num (qmckl_context context, const int64_t num); +qmckl_exit_code qmckl_set_nucleus_charge (qmckl_context context, const double* charge); +qmckl_exit_code qmckl_set_nucleus_coord (qmckl_context context, const double* coord); ++
+To set the number of nuclei, use +
+ ++The following function sets the nuclear charges of all the atoms. +
+ ++The following function sets the nuclear coordinates of all the +atoms. The coordinates should be given in atomic units. +
+1.4 Test
+/* Reference input data */ + +#define num ((int64_t) 9) + +double charge[num] = { 6., 6., 6., 7., 7., 1., 1., 1., 1. }; + +double coord[3*num] = + { 4.166279566732572e-01, -1.526183863767697e+00, 1.041604719335635e+00, + -1.903457631371503e+00, 2.242154435363994e+00, 6.550163404813796e-01, + -3.575005445908036e+00, -3.063638942318878e+00, 2.086739409279095e+00, + 2.060062599100338e+00, -1.623431626827498e+00, -1.930074272670425e+00, + 9.491495662916423e-01, 3.808343139803397e-01, 4.077482772289367e+00, + 1.841031662652821e+00, -2.945591662994877e+00, -3.670011011125464e+00, + 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, + 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, + 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00}; + +/* --- */ + +qmckl_exit_code rc; + +assert(!qmckl_nucleus_provided(context)); + +int64_t n; +rc = qmckl_get_nucleus_num (context, &n); +assert(rc == QMCKL_NOT_PROVIDED); + + +rc = qmckl_set_nucleus_num (context, num); +assert(rc == QMCKL_SUCCESS); +assert(!qmckl_nucleus_provided(context)); + +rc = qmckl_get_nucleus_num (context, &n); +assert(rc == QMCKL_SUCCESS); +assert(n == num); + +double coord2[3*num]; + +rc = qmckl_get_nucleus_coord (context, coord2); +assert(rc == QMCKL_NOT_PROVIDED); + +rc = qmckl_set_nucleus_coord (context, coord); +assert(rc == QMCKL_SUCCESS); + +rc = qmckl_get_nucleus_coord (context, coord2); +assert(rc == QMCKL_SUCCESS); +for (size_t i=0 ; i<3*num ; ++i) { + assert( coord[i] == coord2[i] ); + } + +assert(!qmckl_nucleus_provided(context)); + +double charge2[num]; + +rc = qmckl_get_nucleus_charge(context, charge2); +assert(rc == QMCKL_NOT_PROVIDED); + +rc = qmckl_set_nucleus_charge(context, charge); +assert(rc == QMCKL_SUCCESS); + +rc = qmckl_get_nucleus_charge(context, charge2); +assert(rc == QMCKL_SUCCESS); +for (size_t i=0 ; i<num ; ++i) { + assert( charge[i] == charge2[i] ); + } +assert(qmckl_nucleus_provided(context)); ++
2 Computation
++The computed data is stored in the context so that it can be reused +by different kernels. To ensure that the data is valid, for each +computed data the date of the context is stored when it is computed. +To know if some data needs to be recomputed, we check if the date of +the dependencies are more recent than the date of the data to +compute. If it is the case, then the data is recomputed and the +current date is stored. +
+2.1 Nucleus-nucleus distances
+2.1.1 Get
+qmckl_exit_code qmckl_get_nucleus_nn_distance(qmckl_context context, double* distance); ++
2.1.2 Compute
+qmcklcontext | +context | +in | +Global state | +
int64t | +nuclnum | +in | +Number of nuclei | +
double | +coord[3][nuclnum] | +in | +Nuclear coordinates (au) | +
double | +nndistance[nuclnum][nuclnum] | +out | +Nucleus-nucleus distances (au) | +
integer function qmckl_compute_nn_distance_f(context, nucl_num, coord, nn_distance) & + result(info) + use qmckl + implicit none + integer(qmckl_context), intent(in) :: context + integer*8 , intent(in) :: nucl_num + double precision , intent(in) :: coord(nucl_num,3) + double precision , intent(out) :: nn_distance(nucl_num,nucl_num) + + integer*8 :: k + + info = QMCKL_SUCCESS + + if (context == QMCKL_NULL_CONTEXT) then + info = QMCKL_INVALID_CONTEXT + return + endif + + if (nucl_num <= 0) then + info = QMCKL_INVALID_ARG_2 + return + endif + + info = qmckl_distance(context, 'T', 'T', nucl_num, nucl_num, & + coord, nucl_num, & + coord, nucl_num, & + nn_distance, nucl_num) + +end function qmckl_compute_nn_distance_f ++
2.1.3 Test
+/* Reference input data */ + +assert(qmckl_nucleus_provided(context)); + +double distance[num*num]; +rc = qmckl_get_nucleus_nn_distance(context, distance); +rc = qmckl_get_nucleus_nn_distance(context, distance); +assert(distance[0] == 0.); +assert(distance[1] == distance[num]); +assert(abs(distance[1]-4.164450441785663) < 1.e-12); + ++
2.2 Nuclear repulsion energy
++\[ + V_{NN} = \sum_{A=1}^{N-1} \sum_{B>A}^N \frac{Q_A Q_B}{R_{AB}} + \] +
+2.2.1 Get
+qmckl_exit_code qmckl_get_nucleus_repulsion(qmckl_context context, double* energy); ++
2.2.2 Compute
+qmcklcontext | +context | +in | +Global state | +
int64t | +nuclnum | +in | +Number of nuclei | +
double | +charge[nuclnum] | +in | +Nuclear charges (au) | +
double | +nndistance[nuclnum][nuclnum] | +in | +Nucleus-nucleus distances (au) | +
double | +energy | +out | +Nuclear repulsion energy | +
integer function qmckl_compute_nucleus_repulsion_f(context, nucl_num, charge, nn_distance, energy) & + result(info) + use qmckl + implicit none + integer(qmckl_context), intent(in) :: context + integer*8 , intent(in) :: nucl_num + double precision , intent(in) :: charge(nucl_num) + double precision , intent(in) :: nn_distance(nucl_num,nucl_num) + double precision , intent(out) :: energy + + integer*8 :: i, j + + info = QMCKL_SUCCESS + + if (context == QMCKL_NULL_CONTEXT) then + info = QMCKL_INVALID_CONTEXT + return + endif + + if (nucl_num <= 0) then + info = QMCKL_INVALID_ARG_2 + return + endif + + energy = 0.d0 + do j=2, nucl_num + do i=1, j-1 + energy = energy + charge(i) * charge(j) / nn_distance(i,j) + end do + end do + print *, energy + +end function qmckl_compute_nucleus_repulsion_f ++
2.2.3 Test
+/* Reference input data */ + +assert(qmckl_nucleus_provided(context)); + +double rep; +rc = qmckl_get_nucleus_repulsion(context, &rep); +assert(rep - 163.50434957121263 < 1.e-10); + ++