mirror of
https://github.com/TREX-CoE/qmckl.git
synced 2024-08-25 06:31:45 +02:00
Version 0.4.1
This commit is contained in:
parent
bbf596bb4c
commit
5d1373a2fb
@ -35,7 +35,7 @@
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
|
||||
AC_INIT([qmckl],[0.3.1],[https://github.com/TREX-CoE/qmckl/issues],[],[https://trex-coe.github.io/qmckl/index.html])
|
||||
AC_INIT([qmckl],[0.4.1],[https://github.com/TREX-CoE/qmckl/issues],[],[https://trex-coe.github.io/qmckl/index.html])
|
||||
AC_CONFIG_AUX_DIR([tools])
|
||||
AM_INIT_AUTOMAKE([subdir-objects color-tests parallel-tests silent-rules 1.11])
|
||||
|
||||
|
@ -82,6 +82,223 @@ rmin = np.array( list([ np.min(nucl_coord[:,a]) for a in range(3) ]) )
|
||||
rmax = np.array( list([ np.max(nucl_coord[:,a]) for a in range(3) ]) )
|
||||
|
||||
|
||||
linspace = [ None for i in range(3) ]
|
||||
step = [ None for i in range(3) ]
|
||||
for a in range(3):
|
||||
linspace[a], step[a] = np.linspace(rmin[a]-shift[a],
|
||||
rmax[a]+shift[a],
|
||||
num=nx[a],
|
||||
retstep=True)
|
||||
|
||||
dr = step[0] * step[1] * step[2]
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
|
||||
Now the grid is ready, we can create the list of grid points
|
||||
$\mathbf{r}_k$ on which the MOs $\phi_i$ will be evaluated, and
|
||||
transfer them to the QMCkl context:
|
||||
|
||||
#+begin_src python :exports code
|
||||
point = []
|
||||
for x in linspace[0]:
|
||||
for y in linspace[1]:
|
||||
for z in linspace[2]:
|
||||
point += [ [x, y, z] ]
|
||||
|
||||
point = np.array(point)
|
||||
point_num = len(point)
|
||||
qmckl.set_point(context, 'N', point_num, np.reshape(point, (point_num*3)))
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
: None
|
||||
|
||||
Then, we evaluate all the MOs at the grid points (and time the execution),
|
||||
and thus obtain the matrix $M_{ki} = \langle \mathbf{r}_k | \phi_i \rangle =
|
||||
\phi_i(\mathbf{r}_k)$.
|
||||
|
||||
#+begin_src python :exports code
|
||||
import time
|
||||
|
||||
mo_num = qmckl.get_mo_basis_mo_num(context)
|
||||
|
||||
before = time.time()
|
||||
mo_value = qmckl.get_mo_basis_mo_value(context, point_num*mo_num)
|
||||
after = time.time()
|
||||
|
||||
mo_value = np.reshape( mo_value, (point_num, mo_num) )
|
||||
|
||||
print("Number of MOs: ", mo_num)
|
||||
print("Number of grid points: ", point_num)
|
||||
print("Execution time : ", (after - before), "seconds")
|
||||
|
||||
#+end_src
|
||||
|
||||
#+begin_example
|
||||
Number of MOs: 201
|
||||
Number of grid points: 1728000
|
||||
Execution time : 3.511528968811035 seconds
|
||||
#+end_example
|
||||
|
||||
and finally we compute the overlap between all the MOs as
|
||||
$M^\dagger M$.
|
||||
|
||||
#+begin_src python :exports code
|
||||
overlap = mo_value.T @ mo_value * dr
|
||||
print (overlap)
|
||||
#+end_src
|
||||
|
||||
#+begin_example
|
||||
[[ 9.88693941e-01 2.34719693e-03 -1.50518232e-08 ... 3.12084178e-09
|
||||
-5.81064929e-10 3.70130091e-02]
|
||||
[ 2.34719693e-03 9.99509628e-01 3.18930040e-09 ... -2.46888958e-10
|
||||
-1.06064273e-09 -7.65567973e-03]
|
||||
[-1.50518232e-08 3.18930040e-09 9.99995073e-01 ... -5.84882580e-06
|
||||
-1.21598117e-06 4.59036468e-08]
|
||||
...
|
||||
[ 3.12084178e-09 -2.46888958e-10 -5.84882580e-06 ... 1.00019107e+00
|
||||
-2.03342837e-04 -1.36954855e-08]
|
||||
[-5.81064929e-10 -1.06064273e-09 -1.21598117e-06 ... -2.03342837e-04
|
||||
9.99262427e-01 1.18264754e-09]
|
||||
[ 3.70130091e-02 -7.65567973e-03 4.59036468e-08 ... -1.36954855e-08
|
||||
1.18264754e-09 8.97215950e-01]]
|
||||
#+end_example
|
||||
|
||||
* C
|
||||
** Check numerically that MOs are orthonormal, with cusp fitting
|
||||
|
||||
In this example, we will compute numerically the overlap
|
||||
between the molecular orbitals:
|
||||
|
||||
\[
|
||||
S_{ij} = \int \phi_i(\mathbf{r}) \phi_j(\mathbf{r})
|
||||
\text{d}\mathbf{r} \sim \sum_{k=1}^{N} \phi_i(\mathbf{r}_k)
|
||||
\phi_j(\mathbf{r}_k) \delta \mathbf{r}
|
||||
\]
|
||||
\[
|
||||
S_{ij} = \langle \phi_i | \phi_j \rangle
|
||||
\sim \sum_{k=1}^{N} \langle \phi_i | \mathbf{r}_k \rangle
|
||||
\langle \mathbf{r}_k | \phi_j \rangle
|
||||
\]
|
||||
|
||||
We apply the cusp fitting procedure, so the MOs might deviate
|
||||
slightly from orthonormality.
|
||||
|
||||
#+begin_src c :exports code
|
||||
#include <qmckl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* trexio_filename = "..//share/qmckl/test_data/h2o_5z.h5";
|
||||
qmckl_exit_code rc = QMCKL_SUCCESS;
|
||||
#+end_src
|
||||
|
||||
First, we create a context for the QMCkl calculation, and load the
|
||||
wave function stored in =h2o_5z.h5= inside it. It is a Hartree-Fock
|
||||
determinant for the water molecule in the cc-pV5Z basis set.
|
||||
|
||||
#+begin_src c :exports code
|
||||
qmckl_context context = qmckl_context_create();
|
||||
if (context == NULL) {
|
||||
fprintf(stderr, "Error creating context\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rc = qmckl_trexio_read(context, trexio_filename, strlen(trexio_filename));
|
||||
|
||||
if (rc != QMCKL_SUCCESS) {
|
||||
fprintf(stderr, "Error reading TREXIO file:\n%s\n", qmckl_string_of_error(rc));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#+end_src
|
||||
|
||||
We impose the electron-nucleus cusp fitting to occur when the
|
||||
electrons are close to the nuclei. The critical distance
|
||||
is 0.5 atomic units for hydrogens and 0.1 for the oxygen.
|
||||
To identify which atom is an oxygen and which are hydrogens, we
|
||||
fetch the nuclear charges from the context.
|
||||
|
||||
#+begin_src python :exports code
|
||||
int64_t nucl_num;
|
||||
|
||||
rc = qmckl_get_nucleus_num(context, &nucl_num);
|
||||
|
||||
if (rc != QMCKL_SUCCESS) {
|
||||
fprintf(stderr, "Error getting nucl_num:\n%s\n", qmckl_string_of_error(rc));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
double nucl_charge[nucl_num];
|
||||
|
||||
rc = qmckl_get_nucleus_charge(context, &(nucl_charge[0]));
|
||||
|
||||
if (rc != QMCKL_SUCCESS) {
|
||||
fprintf(stderr, "Error getting nucl_charge:\n%s\n", qmckl_string_of_error(rc));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
double r_c[nucl_num];
|
||||
|
||||
for (size_t i=0 ; i<nucl_num ; ++i) {
|
||||
|
||||
switch ((int) nucl_charge[i]) {
|
||||
case 1:
|
||||
nucl_charge[i] = 0.5;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
nucl_charge[i] = 0.1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#+end_src
|
||||
|
||||
#+begin_src python :exports code
|
||||
double nucl_coord[nucl_num][3];
|
||||
|
||||
rc = qmckl_get_nucleus_coord(context, 'N', &(nucl_coord[0][0]), nucl_num*3)
|
||||
|
||||
if (rc != QMCKL_SUCCESS) {
|
||||
fprintf(stderr, "Error getting nucl_coord:\n%s\n", qmckl_string_of_error(rc));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (size_t i=0 ; i<nucl_num ; ++i) {
|
||||
printf("%d %+f %+f %+f\n", (int32_t) nucl_charge[i],
|
||||
nucl_coord[i][0],
|
||||
nucl_coord[i][1],
|
||||
nucl_coord[i][2]) );
|
||||
#+end_src
|
||||
|
||||
#+begin_example
|
||||
8 +0.000000 +0.000000 +0.000000
|
||||
1 -1.430429 +0.000000 -1.107157
|
||||
1 +1.430429 +0.000000 -1.107157
|
||||
#+end_example
|
||||
|
||||
|
||||
We now define the grid points $\mathbf{r}_k$ as a regular grid around the
|
||||
molecule.
|
||||
We fetch the nuclear coordinates from the context,
|
||||
|
||||
and compute the coordinates of the grid points:
|
||||
|
||||
#+begin_src python :exports code
|
||||
nx = ( 120, 120, 120 )
|
||||
shift = np.array([5.,5.,5.])
|
||||
point_num = nx[0] * nx[1] * nx[2]
|
||||
|
||||
rmin = np.array( list([ np.min(nucl_coord[:,a]) for a in range(3) ]) )
|
||||
rmax = np.array( list([ np.max(nucl_coord[:,a]) for a in range(3) ]) )
|
||||
|
||||
|
||||
linspace = [ None for i in range(3) ]
|
||||
step = [ None for i in range(3) ]
|
||||
for a in range(3):
|
||||
|
Loading…
Reference in New Issue
Block a user