2021-04-21 01:56:47 +02:00
|
|
|
#+TITLE: Electrons
|
2021-04-30 01:26:19 +02:00
|
|
|
#+SETUPFILE: ../tools/theme.setup
|
2021-04-21 01:56:47 +02:00
|
|
|
#+INCLUDE: ../tools/lib.org
|
|
|
|
|
|
|
|
In conventional QMC simulations, up-spin and down-spin electrons are
|
|
|
|
different. The ~electron~ data structure contains the number of
|
|
|
|
up-spin and down-spin electrons, and the electron coordinates.
|
|
|
|
|
|
|
|
* Headers :noexport:
|
2021-04-30 01:26:19 +02:00
|
|
|
#+begin_src elisp :noexport :results none
|
2021-04-21 01:56:47 +02:00
|
|
|
(org-babel-lob-ingest "../tools/lib.org")
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
|
|
|
|
#+begin_src c :tangle (eval h_private_type)
|
|
|
|
#ifndef QMCKL_ELECTRON_HPT
|
|
|
|
#define QMCKL_ELECTRON_HPT
|
|
|
|
#include <stdbool.h>
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+begin_src c :tangle (eval c_test) :noweb yes
|
|
|
|
#include "qmckl.h"
|
|
|
|
#include "munit.h"
|
2021-05-10 10:05:50 +02:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2021-05-10 10:41:59 +02:00
|
|
|
#include "config.h"
|
2021-05-09 02:12:38 +02:00
|
|
|
#endif
|
2021-04-21 01:56:47 +02:00
|
|
|
MunitResult test_<<filename()>>() {
|
|
|
|
qmckl_context context;
|
|
|
|
context = qmckl_context_create();
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+begin_src c :tangle (eval c)
|
2021-05-10 10:05:50 +02:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2021-05-10 10:41:59 +02:00
|
|
|
#include "config.h"
|
2021-05-09 02:12:38 +02:00
|
|
|
#endif
|
2021-05-10 10:05:50 +02:00
|
|
|
|
|
|
|
#ifdef HAVE_STDINT_H
|
2021-04-21 01:56:47 +02:00
|
|
|
#include <stdint.h>
|
2021-05-10 10:05:50 +02:00
|
|
|
#elif HAVE_INTTYPES_H
|
|
|
|
#include <inttypes.h>
|
|
|
|
#endif
|
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <assert.h>
|
2021-04-26 01:45:25 +02:00
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2021-04-21 01:56:47 +02:00
|
|
|
|
2021-05-11 13:57:23 +02:00
|
|
|
#include "qmckl.h"
|
2021-04-21 01:56:47 +02:00
|
|
|
#include "qmckl_context_private_type.h"
|
|
|
|
#include "qmckl_memory_private_type.h"
|
|
|
|
#include "qmckl_memory_private_func.h"
|
2021-04-26 01:45:25 +02:00
|
|
|
#include "qmckl_electron_private_func.h"
|
2021-04-21 01:56:47 +02:00
|
|
|
#+end_src
|
|
|
|
|
|
|
|
* Context
|
|
|
|
|
|
|
|
The following data stored in the context:
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
| ~uninitialized~ | int32_t | Keeps bit set for uninitialized data |
|
|
|
|
| ~num~ | int64_t | Total number of electrons |
|
|
|
|
| ~up_num~ | int64_t | Number of up-spin electrons |
|
|
|
|
| ~down_num~ | int64_t | Number of down-spin electrons |
|
|
|
|
| ~walk_num~ | int64_t | Number of walkers |
|
|
|
|
| ~provided~ | bool | If true, ~electron~ is valid |
|
|
|
|
| ~coord_new~ | double[walk_num][3][num] | New set of electron coordinates |
|
|
|
|
| ~coord_old~ | double[walk_num][3][num] | Old set of electron coordinates |
|
|
|
|
| ~coord_new_date~ | uint64_t | Last modification date of the coordinates |
|
2021-04-28 12:08:53 +02:00
|
|
|
| ~ee_distance~ | double[walk_num][num][num] | Electron-electron distances |
|
2021-04-26 01:45:25 +02:00
|
|
|
| ~ee_distance_date~ | uint64_t | Last modification date of the electron-electron distances |
|
2021-04-21 01:56:47 +02:00
|
|
|
|
|
|
|
** Data structure
|
|
|
|
|
|
|
|
#+begin_src c :comments org :tangle (eval h_private_type)
|
|
|
|
typedef struct qmckl_electron_struct {
|
|
|
|
int64_t num;
|
|
|
|
int64_t up_num;
|
|
|
|
int64_t down_num;
|
|
|
|
int64_t walk_num;
|
2021-04-26 01:45:25 +02:00
|
|
|
int64_t coord_new_date;
|
|
|
|
int64_t ee_distance_date;
|
2021-04-21 01:56:47 +02:00
|
|
|
double* coord_new;
|
|
|
|
double* coord_old;
|
2021-04-26 01:45:25 +02:00
|
|
|
double* ee_distance;
|
2021-04-21 01:56:47 +02:00
|
|
|
int32_t uninitialized;
|
|
|
|
bool provided;
|
|
|
|
} qmckl_electron_struct;
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
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~.
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
** Access functions
|
|
|
|
|
2021-04-21 13:00:24 +02:00
|
|
|
#+begin_src c :comments org :tangle (eval h_private_func) :exports none
|
2021-04-21 01:56:47 +02:00
|
|
|
int64_t qmckl_get_electron_num (const qmckl_context context);
|
|
|
|
int64_t qmckl_get_electron_up_num (const qmckl_context context);
|
|
|
|
int64_t qmckl_get_electron_down_num (const qmckl_context context);
|
|
|
|
int64_t qmckl_get_electron_walk_num (const qmckl_context context);
|
|
|
|
double* qmckl_get_electron_coord_new (const qmckl_context context);
|
|
|
|
double* qmckl_get_electron_coord_old (const qmckl_context context);
|
|
|
|
#+end_src
|
|
|
|
|
2021-04-21 13:00:24 +02:00
|
|
|
When all the data relative to electrons have been set, the
|
|
|
|
following function returns ~true~.
|
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
#+begin_src c :comments org :tangle (eval h_func)
|
|
|
|
bool qmckl_electron_provided (const qmckl_context context);
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+NAME:post
|
2021-04-21 13:00:24 +02:00
|
|
|
#+begin_src c :exports none
|
2021-04-21 01:56:47 +02:00
|
|
|
if ( (ctx->electron.uninitialized & mask) != 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#+end_src
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 13:00:24 +02:00
|
|
|
#+begin_src c :comments org :tangle (eval c) :noweb yes :exports none
|
2021-04-21 01:56:47 +02:00
|
|
|
int64_t qmckl_get_electron_num (const qmckl_context context) {
|
|
|
|
|
|
|
|
if (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) {
|
|
|
|
return (char) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_context_struct* const ctx = (qmckl_context_struct* const) context;
|
|
|
|
assert (ctx != NULL);
|
|
|
|
|
|
|
|
int32_t mask = 1;
|
|
|
|
|
|
|
|
if ( (ctx->electron.uninitialized & mask) != 0) {
|
|
|
|
return (int64_t) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert (ctx->electron.num > (int64_t) 0);
|
|
|
|
return ctx->electron.num;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int64_t qmckl_get_electron_up_num (const qmckl_context context) {
|
|
|
|
if (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) {
|
|
|
|
return (int64_t) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_context_struct* const ctx = (qmckl_context_struct* const) context;
|
|
|
|
assert (ctx != NULL);
|
|
|
|
|
|
|
|
int32_t mask = 1 << 1;
|
|
|
|
|
|
|
|
if ( (ctx->electron.uninitialized & mask) != 0) {
|
|
|
|
return (int64_t) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert (ctx->electron.up_num > (int64_t) 0);
|
|
|
|
return ctx->electron.up_num;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int64_t qmckl_get_electron_down_num (const qmckl_context context) {
|
|
|
|
if (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) {
|
|
|
|
return (int64_t) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_context_struct* const ctx = (qmckl_context_struct* const) context;
|
|
|
|
assert (ctx != NULL);
|
|
|
|
|
|
|
|
int32_t mask = 1 << 2;
|
|
|
|
|
|
|
|
if ( (ctx->electron.uninitialized & mask) != 0) {
|
|
|
|
return (int64_t) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert (ctx->electron.down_num >= (int64_t) 0);
|
|
|
|
return ctx->electron.down_num;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int64_t qmckl_get_electron_walk_num (const qmckl_context context) {
|
|
|
|
if (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) {
|
|
|
|
return (int64_t) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_context_struct* const ctx = (qmckl_context_struct* const) context;
|
|
|
|
assert (ctx != NULL);
|
|
|
|
|
|
|
|
int32_t mask = 1 << 3;
|
|
|
|
|
|
|
|
if ( (ctx->electron.uninitialized & mask) != 0) {
|
|
|
|
return (int64_t) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert (ctx->electron.walk_num > (int64_t) 0);
|
|
|
|
return ctx->electron.walk_num;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool qmckl_electron_provided(const qmckl_context context) {
|
|
|
|
|
|
|
|
if (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_context_struct* const ctx = (qmckl_context_struct* const) context;
|
|
|
|
assert (ctx != NULL);
|
|
|
|
|
|
|
|
return ctx->electron.provided;
|
|
|
|
}
|
|
|
|
#+end_src
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
** Initialization functions
|
|
|
|
|
|
|
|
To set the data relative to the electrons in the context, the
|
|
|
|
following functions need to be called. When the data structure is
|
|
|
|
initialized, the ~coord_new~ and ~coord_old~ arrays are both allocated.
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
#+begin_src c :comments org :tangle (eval h_func)
|
|
|
|
qmckl_exit_code qmckl_set_electron_num (qmckl_context context, const int64_t up_num, const int64_t down_num);
|
|
|
|
qmckl_exit_code qmckl_set_electron_walk_num (qmckl_context context, const int64_t walk_num);
|
|
|
|
qmckl_exit_code qmckl_set_electron_coord (qmckl_context context, const double* coord);
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+NAME:pre2
|
2021-04-21 13:00:24 +02:00
|
|
|
#+begin_src c :exports none
|
2021-04-21 01:56:47 +02:00
|
|
|
if (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) {
|
|
|
|
return QMCKL_NULL_CONTEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_context_struct* const ctx = (qmckl_context_struct* const) context;
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+NAME:post2
|
2021-04-21 13:00:24 +02:00
|
|
|
#+begin_src c :exports none
|
2021-04-30 01:26:19 +02:00
|
|
|
ctx->electron.uninitialized &= ~mask;
|
2021-04-21 01:56:47 +02:00
|
|
|
ctx->electron.provided = (ctx->electron.uninitialized == 0);
|
|
|
|
|
|
|
|
if (ctx->electron.provided) {
|
|
|
|
if (ctx->electron.coord_new != NULL) {
|
|
|
|
qmckl_free(context, ctx->electron.coord_new);
|
|
|
|
ctx->electron.coord_new = NULL;
|
|
|
|
}
|
|
|
|
if (ctx->electron.coord_old != NULL) {
|
|
|
|
qmckl_free(context, ctx->electron.coord_old);
|
|
|
|
ctx->electron.coord_old = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_memory_info_struct mem_info = qmckl_memory_info_struct_zero;
|
|
|
|
mem_info.size = ctx->electron.num * ctx->electron.walk_num * 3 * sizeof(double);
|
|
|
|
|
|
|
|
double* coord_new = (double*) qmckl_malloc(context, mem_info);
|
|
|
|
if (coord_new == NULL) {
|
|
|
|
return qmckl_failwith( context,
|
|
|
|
QMCKL_ALLOCATION_FAILED,
|
|
|
|
"qmckl_set_electron_num",
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
ctx->electron.coord_new = coord_new;
|
|
|
|
|
|
|
|
double* coord_old = (double*) qmckl_malloc(context, mem_info);
|
|
|
|
if (coord_old == NULL) {
|
|
|
|
return qmckl_failwith( context,
|
|
|
|
QMCKL_ALLOCATION_FAILED,
|
|
|
|
"qmckl_set_electron_num",
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
ctx->electron.coord_old = coord_old;
|
2021-04-26 01:45:25 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return QMCKL_SUCCESS;
|
|
|
|
#+end_src
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
To set the number of electrons, we give the number of up-spin and
|
2021-04-21 13:00:24 +02:00
|
|
|
down-spin electrons to the context and we set the number of walkers.
|
2021-04-30 01:26:19 +02:00
|
|
|
|
|
|
|
#+begin_src c :comments org :tangle (eval c) :noweb yes :exports none
|
2021-04-21 01:56:47 +02:00
|
|
|
qmckl_exit_code qmckl_set_electron_num(qmckl_context context,
|
|
|
|
const int64_t up_num,
|
|
|
|
const int64_t down_num) {
|
|
|
|
<<pre2>>
|
|
|
|
|
|
|
|
if (up_num <= 0) {
|
|
|
|
return qmckl_failwith( context,
|
|
|
|
QMCKL_INVALID_ARG_2,
|
|
|
|
"qmckl_set_electron_num",
|
|
|
|
"up_num <= 0");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (down_num <= 0) {
|
|
|
|
return qmckl_failwith( context,
|
|
|
|
QMCKL_INVALID_ARG_3,
|
|
|
|
"qmckl_set_electron_num",
|
|
|
|
"down_num <= 0");
|
|
|
|
}
|
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
int32_t mask = 1;
|
2021-04-21 01:56:47 +02:00
|
|
|
|
|
|
|
ctx->electron.up_num = up_num;
|
|
|
|
ctx->electron.down_num = down_num;
|
|
|
|
ctx->electron.num = up_num + down_num;
|
|
|
|
|
|
|
|
<<post2>>
|
|
|
|
}
|
|
|
|
#+end_src
|
2021-04-30 01:26:19 +02:00
|
|
|
|
|
|
|
|
|
|
|
#+begin_src c :comments org :tangle (eval c) :noweb yes :exports none
|
2021-04-21 01:56:47 +02:00
|
|
|
qmckl_exit_code qmckl_set_electron_walk_num(qmckl_context context, const int64_t walk_num) {
|
|
|
|
<<pre2>>
|
|
|
|
|
|
|
|
if (walk_num <= 0) {
|
|
|
|
return qmckl_failwith( context,
|
|
|
|
QMCKL_INVALID_ARG_2,
|
|
|
|
"qmckl_set_electron_walk_num",
|
|
|
|
"walk_num <= 0");
|
|
|
|
}
|
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
int32_t mask = 2;
|
2021-04-21 01:56:47 +02:00
|
|
|
ctx->electron.walk_num = walk_num;
|
|
|
|
|
|
|
|
<<post2>>
|
|
|
|
}
|
|
|
|
#+end_src
|
2021-04-30 01:26:19 +02:00
|
|
|
|
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
The following function sets the electron coordinates of all the
|
|
|
|
walkers. When this is done, the pointers to the old and new sets
|
|
|
|
of coordinates are swapped, and the new coordinates are
|
2021-04-21 13:00:24 +02:00
|
|
|
overwritten. This can be done only when the data relative to
|
|
|
|
electrons have been set.
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 13:00:24 +02:00
|
|
|
#+begin_src c :comments org :tangle (eval c) :noweb yes :exports none
|
2021-04-21 01:56:47 +02:00
|
|
|
qmckl_exit_code qmckl_set_electron_coord(qmckl_context context, const double* coord) {
|
|
|
|
<<pre2>>
|
|
|
|
|
|
|
|
const int64_t num = qmckl_get_electron_num(context);
|
|
|
|
if (num == 0L) {
|
|
|
|
return qmckl_failwith( context,
|
|
|
|
QMCKL_FAILURE,
|
|
|
|
"qmckl_set_electron_coord",
|
|
|
|
"num is not set");
|
|
|
|
}
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
const int64_t walk_num = qmckl_get_electron_walk_num(context);
|
|
|
|
if (walk_num == 0L) {
|
|
|
|
return qmckl_failwith( context,
|
|
|
|
QMCKL_FAILURE,
|
|
|
|
"qmckl_set_electron_coord",
|
|
|
|
"walk_num is not set");
|
|
|
|
}
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
/* If num and walk_num are set, the arrays should be allocated */
|
|
|
|
assert (ctx->electron.coord_old != NULL);
|
|
|
|
assert (ctx->electron.coord_new != NULL);
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
/* Increment the date of the context */
|
|
|
|
ctx->date += 1UL;
|
|
|
|
|
|
|
|
/* Swap pointers */
|
|
|
|
double * swap;
|
|
|
|
swap = ctx->electron.coord_old;
|
|
|
|
ctx->electron.coord_old = ctx->electron.coord_new;
|
|
|
|
ctx->electron.coord_new = swap;
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
memcpy(ctx->electron.coord_new, coord, walk_num * num * 3 * sizeof(double));
|
2021-04-26 01:45:25 +02:00
|
|
|
ctx->electron.coord_new_date = ctx->date;
|
2021-04-21 01:56:47 +02:00
|
|
|
|
|
|
|
return QMCKL_SUCCESS;
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
}
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
** Test
|
|
|
|
|
|
|
|
#+begin_src c :tangle (eval c_test)
|
|
|
|
/* Reference input data */
|
|
|
|
|
|
|
|
#define up_num ((int64_t) 3)
|
|
|
|
#define down_num ((int64_t) 2)
|
|
|
|
#define walk_num ((int64_t) 2)
|
|
|
|
#define num (up_num+down_num)
|
|
|
|
|
|
|
|
double coord[walk_num*3*num] =
|
2021-04-30 01:26:19 +02:00
|
|
|
{ 7.303633091022677881e+00, 1.375868694453235719e+01, 1.167371490471771217e-01,
|
2021-04-21 01:56:47 +02:00
|
|
|
4.547755371567960836e+00, 3.245907105524011182e+00, 2.410764357550297110e-01,
|
|
|
|
5.932816068137344523e+00, 1.491671465549257469e+01, 3.825374039119375236e-01,
|
|
|
|
7.347336142660052083e+00, 1.341946976062362129e+00, 1.648917914228352322e+00,
|
|
|
|
5.735221530102248444e+00, 1.064667491680036271e+01, 4.227201772236627297e-01,
|
|
|
|
8.099550978782254163e+00, 6.861498941099086757e+00, 4.015884841159429036e-02,
|
|
|
|
1.014757367558326173e+01, 5.219335322173662917e+00, 5.037004126899931322e-02,
|
|
|
|
1.484094322159507051e+01, 9.777903829455864226e+00, 5.243007994024882767e-02,
|
|
|
|
9.081723054990456845e+00, 5.499568496038920173e+00, 2.910446438899221347e-02,
|
|
|
|
2.583154239492383653e+00, 1.442282811294904432e+00, 6.387191629878670451e-02 };
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
/* --- */
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
qmckl_exit_code rc;
|
|
|
|
|
|
|
|
munit_assert(!qmckl_electron_provided(context));
|
|
|
|
|
|
|
|
rc = qmckl_set_electron_num (context, up_num, down_num);
|
|
|
|
munit_assert_int64(rc, ==, QMCKL_SUCCESS);
|
|
|
|
munit_assert(!qmckl_electron_provided(context));
|
|
|
|
|
|
|
|
rc = qmckl_set_electron_walk_num (context, walk_num);
|
|
|
|
munit_assert_int64(rc, ==, QMCKL_SUCCESS);
|
|
|
|
munit_assert(qmckl_electron_provided(context));
|
|
|
|
|
|
|
|
rc = qmckl_set_electron_coord (context, coord);
|
|
|
|
munit_assert_int64(rc, ==, QMCKL_SUCCESS);
|
|
|
|
|
|
|
|
#+end_src
|
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
* Computation
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
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.
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
** Electron-electron distances
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
*** Get
|
|
|
|
|
|
|
|
#+begin_src c :comments org :tangle (eval h_func) :noweb yes
|
|
|
|
qmckl_exit_code qmckl_get_electron_ee_distance(qmckl_context context, double* distance);
|
|
|
|
#+end_src
|
2021-04-30 01:26:19 +02:00
|
|
|
|
|
|
|
#+begin_src c :comments org :tangle (eval c) :noweb yes :exports none
|
2021-04-26 01:45:25 +02:00
|
|
|
qmckl_exit_code qmckl_get_electron_ee_distance(qmckl_context context, double* distance)
|
|
|
|
{
|
|
|
|
/* Check input parameters */
|
|
|
|
if (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) {
|
|
|
|
return (char) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_exit_code rc = qmckl_provide_ee_distance(context);
|
|
|
|
if (rc != QMCKL_SUCCESS) return rc;
|
|
|
|
|
|
|
|
qmckl_context_struct* const ctx = (qmckl_context_struct* const) context;
|
|
|
|
assert (ctx != NULL);
|
|
|
|
|
|
|
|
size_t sze = ctx->electron.num * ctx->electron.num * ctx->electron.walk_num;
|
|
|
|
memcpy(distance, ctx->electron.ee_distance, sze * sizeof(double));
|
|
|
|
|
|
|
|
return QMCKL_SUCCESS;
|
|
|
|
}
|
|
|
|
#+end_src
|
|
|
|
*** Provide :noexport:
|
2021-04-30 01:26:19 +02:00
|
|
|
|
|
|
|
#+begin_src c :comments org :tangle (eval h_private_func) :noweb yes :exports none
|
2021-04-26 01:45:25 +02:00
|
|
|
qmckl_exit_code qmckl_provide_ee_distance(qmckl_context context);
|
|
|
|
#+end_src
|
2021-04-30 01:26:19 +02:00
|
|
|
|
|
|
|
#+begin_src c :comments org :tangle (eval c) :noweb yes :exports none
|
2021-04-26 01:45:25 +02:00
|
|
|
qmckl_exit_code qmckl_provide_ee_distance(qmckl_context context)
|
|
|
|
{
|
|
|
|
/* Check input parameters */
|
|
|
|
if (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) {
|
|
|
|
return (char) 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_context_struct* const ctx = (qmckl_context_struct* const) context;
|
|
|
|
assert (ctx != NULL);
|
|
|
|
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
/* Compute if necessary */
|
|
|
|
if (ctx->electron.coord_new_date > ctx->electron.ee_distance_date) {
|
|
|
|
|
|
|
|
/* Allocate array */
|
|
|
|
if (ctx->electron.ee_distance == NULL) {
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
qmckl_memory_info_struct mem_info = qmckl_memory_info_struct_zero;
|
|
|
|
mem_info.size = ctx->electron.num * ctx->electron.num *
|
|
|
|
ctx->electron.walk_num * sizeof(double);
|
|
|
|
double* ee_distance = (double*) qmckl_malloc(context, mem_info);
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
if (ee_distance == NULL) {
|
|
|
|
return qmckl_failwith( context,
|
|
|
|
QMCKL_ALLOCATION_FAILED,
|
|
|
|
"qmckl_ee_distance",
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
ctx->electron.ee_distance = ee_distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
qmckl_exit_code rc =
|
|
|
|
qmckl_compute_ee_distance(context,
|
2021-04-30 01:26:19 +02:00
|
|
|
ctx->electron.num,
|
2021-04-26 01:45:25 +02:00
|
|
|
ctx->electron.walk_num,
|
|
|
|
ctx->electron.coord_new,
|
|
|
|
ctx->electron.ee_distance);
|
|
|
|
if (rc != QMCKL_SUCCESS) {
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->electron.ee_distance_date = ctx->date;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QMCKL_SUCCESS;
|
|
|
|
}
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Compute
|
|
|
|
:PROPERTIES:
|
|
|
|
:Name: qmckl_compute_ee_distance
|
|
|
|
:CRetType: qmckl_exit_code
|
|
|
|
:FRetType: qmckl_exit_code
|
|
|
|
:END:
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
#+NAME: qmckl_ee_distance_args
|
|
|
|
| qmckl_context | context | in | Global state |
|
|
|
|
| int64_t | elec_num | in | Number of electrons |
|
|
|
|
| int64_t | walk_num | in | Number of walkers |
|
|
|
|
| double | coord[walk_num][3][elec_num] | in | Electron coordinates |
|
|
|
|
| double | ee_distance[walk_num][elec_num][elec_num] | out | Electron-electron distances |
|
|
|
|
|
|
|
|
#+begin_src f90 :comments org :tangle (eval f) :noweb yes
|
|
|
|
integer function qmckl_compute_ee_distance_f(context, elec_num, walk_num, coord, ee_distance) &
|
|
|
|
result(info)
|
|
|
|
use qmckl
|
|
|
|
implicit none
|
|
|
|
integer(qmckl_context), intent(in) :: context
|
|
|
|
integer*8 , intent(in) :: elec_num
|
|
|
|
integer*8 , intent(in) :: walk_num
|
|
|
|
double precision , intent(in) :: coord(elec_num,3,walk_num)
|
|
|
|
double precision , intent(out) :: ee_distance(elec_num,elec_num,walk_num)
|
|
|
|
|
|
|
|
integer*8 :: k
|
|
|
|
|
|
|
|
info = QMCKL_SUCCESS
|
|
|
|
|
2021-04-30 01:26:19 +02:00
|
|
|
if (context == QMCKL_NULL_CONTEXT) then
|
|
|
|
info = QMCKL_INVALID_CONTEXT
|
|
|
|
return
|
2021-04-26 01:45:25 +02:00
|
|
|
endif
|
|
|
|
|
2021-04-30 01:26:19 +02:00
|
|
|
if (elec_num <= 0) then
|
2021-04-26 01:45:25 +02:00
|
|
|
info = QMCKL_INVALID_ARG_2
|
2021-04-30 01:26:19 +02:00
|
|
|
return
|
2021-04-26 01:45:25 +02:00
|
|
|
endif
|
|
|
|
|
2021-04-30 01:26:19 +02:00
|
|
|
if (walk_num <= 0) then
|
2021-04-26 01:45:25 +02:00
|
|
|
info = QMCKL_INVALID_ARG_3
|
2021-04-30 01:26:19 +02:00
|
|
|
return
|
2021-04-26 01:45:25 +02:00
|
|
|
endif
|
|
|
|
|
|
|
|
!$OMP PARALLEL DO DEFAULT(NONE) &
|
|
|
|
!$OMP SHARED(elec_num, walk_num, coord, ee_distance)
|
|
|
|
!$OMP PRIVATE(k)
|
|
|
|
do k=1,walk_num
|
|
|
|
info = qmckl_distance(context, 'T', 'T', elec_num, elec_num, &
|
|
|
|
coord(1,1,k), elec_num, &
|
|
|
|
coord(1,1,k), elec_num, &
|
|
|
|
ee_distance(1,1,k), elec_num)
|
|
|
|
end do
|
|
|
|
!$OMP END PARALLEL DO
|
|
|
|
|
|
|
|
end function qmckl_compute_ee_distance_f
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+begin_src c :tangle (eval h_private_func) :comments org :exports none
|
|
|
|
qmckl_exit_code qmckl_compute_ee_distance (
|
|
|
|
const qmckl_context context,
|
|
|
|
const int64_t elec_num,
|
|
|
|
const int64_t walk_num,
|
|
|
|
const double* coord,
|
2021-04-30 01:26:19 +02:00
|
|
|
double* const ee_distance );
|
2021-04-26 01:45:25 +02:00
|
|
|
#+end_src
|
|
|
|
|
|
|
|
#+CALL: generate_c_interface(table=qmckl_ee_distance_args,rettyp=get_value("CRetType"),fname=get_value("Name"))
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-26 01:45:25 +02:00
|
|
|
#+RESULTS:
|
|
|
|
#+begin_src f90 :tangle (eval f) :comments org :exports none
|
|
|
|
integer(c_int32_t) function qmckl_compute_ee_distance &
|
|
|
|
(context, elec_num, walk_num, coord, ee_distance) &
|
|
|
|
bind(C) result(info)
|
|
|
|
|
|
|
|
use, intrinsic :: iso_c_binding
|
|
|
|
implicit none
|
|
|
|
|
|
|
|
integer (c_int64_t) , intent(in) , value :: context
|
|
|
|
integer (c_int64_t) , intent(in) , value :: elec_num
|
|
|
|
integer (c_int64_t) , intent(in) , value :: walk_num
|
|
|
|
real (c_double ) , intent(in) :: coord(elec_num,3,walk_num)
|
|
|
|
real (c_double ) , intent(out) :: ee_distance(elec_num,elec_num,walk_num)
|
|
|
|
|
|
|
|
integer(c_int32_t), external :: qmckl_compute_ee_distance_f
|
|
|
|
info = qmckl_compute_ee_distance_f &
|
|
|
|
(context, elec_num, walk_num, coord, ee_distance)
|
|
|
|
|
|
|
|
end function qmckl_compute_ee_distance
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Test
|
|
|
|
|
|
|
|
#+begin_src c :tangle (eval c_test)
|
|
|
|
/* Reference input data */
|
|
|
|
|
|
|
|
munit_assert(qmckl_electron_provided(context));
|
|
|
|
|
|
|
|
double distance[walk_num*num*num];
|
|
|
|
rc = qmckl_get_electron_ee_distance(context, distance);
|
|
|
|
rc = qmckl_get_electron_ee_distance(context, distance);
|
|
|
|
munit_assert_double(distance[0], ==, 0.);
|
|
|
|
munit_assert_double(distance[1], ==, distance[num]);
|
|
|
|
munit_assert_double_equal(distance[1], 8.6114953086801, 12);
|
|
|
|
|
|
|
|
#+end_src
|
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
* End of files :noexport:
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
#+begin_src c :tangle (eval h_private_type)
|
|
|
|
#endif
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Test
|
|
|
|
#+begin_src c :tangle (eval c_test)
|
|
|
|
if (qmckl_context_destroy(context) != QMCKL_SUCCESS)
|
|
|
|
return QMCKL_FAILURE;
|
|
|
|
return MUNIT_OK;
|
|
|
|
}
|
|
|
|
#+end_src
|
2021-04-30 01:26:19 +02:00
|
|
|
|
|
|
|
**✸ Compute file names
|
|
|
|
#+begin_src emacs-lisp
|
|
|
|
; The following is required to compute the file names
|
|
|
|
|
|
|
|
(setq pwd (file-name-directory buffer-file-name))
|
|
|
|
(setq name (file-name-nondirectory (substring buffer-file-name 0 -4)))
|
|
|
|
(setq f (concat pwd name "_f.f90"))
|
|
|
|
(setq fh (concat pwd name "_fh.f90"))
|
|
|
|
(setq c (concat pwd name ".c"))
|
|
|
|
(setq h (concat name ".h"))
|
|
|
|
(setq h_private (concat name "_private.h"))
|
|
|
|
(setq c_test (concat pwd "test_" name ".c"))
|
|
|
|
(setq f_test (concat pwd "test_" name "_f.f90"))
|
|
|
|
|
|
|
|
; Minted
|
|
|
|
(require 'ox-latex)
|
|
|
|
(setq org-latex-listings 'minted)
|
|
|
|
(add-to-list 'org-latex-packages-alist '("" "listings"))
|
|
|
|
(add-to-list 'org-latex-packages-alist '("" "color"))
|
|
|
|
|
|
|
|
#+end_src
|
2021-04-21 01:56:47 +02:00
|
|
|
|
|
|
|
#+RESULTS:
|
|
|
|
| | color |
|
|
|
|
| | listings |
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
|
|
|
|
# -*- mode: org -*-
|
|
|
|
# vim: syntax=c
|
2021-04-30 01:26:19 +02:00
|
|
|
|
2021-04-21 01:56:47 +02:00
|
|
|
|