1
0
mirror of https://github.com/TREX-CoE/qmckl.git synced 2024-07-17 16:33:59 +02:00

Fix tests

This commit is contained in:
Anthony Scemama 2022-05-20 19:22:56 +02:00
parent e00e034497
commit bd299126c1
2 changed files with 167 additions and 59 deletions

View File

@ -3,17 +3,124 @@
#+INCLUDE: ../tools/lib.org #+INCLUDE: ../tools/lib.org
In this section, we present examples of usage of QMCkl. In this section, we present examples of usage of QMCkl.
For simplicity, we assume that the wave function parameters are stores For simplicity, we assume that the wave function parameters are stored
in a [[https://github.com/TREX-CoE/trexio][TREXIO]] file. in a [[https://github.com/TREX-CoE/trexio][TREXIO]] file.
* Checking errors * Python
All QMCkl functions return an error code. A convenient way to handle ** Check numerically that MOs are orthonormal
errors is to write an error-checking function that displays the
error in text format and exits the program.
#+NAME: qmckl_check_error In this example, we will compute the numerically the overlap
#+begin_src f90 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}
\]
#+begin_src python :session
import numpy as np
import qmckl
#+end_src
#+RESULTS:
First, we create a context for the QMCkl calculation, and load the
wave function stored in =h2o_5z.h5= inside it:
#+begin_src python :session
trexio_filename = "..//share/qmckl/test_data/h2o_5z.h5"
context = qmckl.context_create()
qmckl.trexio_read(context, trexio_filename)
#+end_src
#+RESULTS:
: None
We now define the grid points as a regular grid around the
molecule.
We fetch the nuclear coordinates from the context,
#+begin_src python :session :results output
nucl_num = qmckl.get_nucleus_num(context)
nucl_charge = qmckl.get_nucleus_charge(context, nucl_num)
nucl_coord = qmckl.get_nucleus_coord(context, 'N', nucl_num*3)
nucl_coord = np.reshape(nucl_coord, (3, nucl_num))
for i in range(nucl_num):
print("%d %+f %+f %+f"%(int(nucl_charge[i]),
nucl_coord[i,0],
nucl_coord[i,1],
nucl_coord[i,2]) )
#+end_src
#+RESULTS:
: 8 +0.000000 +0.000000 +0.000000
: 1 -1.430429 +0.000000 -1.107157
: 1 +1.430429 +0.000000 -1.107157
and compute the coordinates of the grid points:
#+begin_src python :session
nx = ( 40, 40, 40 )
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) ]) )
shift = np.array([5.,5.,5.])
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]
dr
#+end_src
#+RESULTS:
: 0.024081249137090373
Now the grid is ready, we can create the list of grid points on
which the MOs will be evaluated, and transfer them to the QMCkl
context:
#+begin_src python :session
point = []
for x in linspace[0]:
for y in linspace[1]:
for z in linspace[2]:
point += [x, y, z]
#point = np.array(point)
qmckl.set_point(context, 'N', point, len(point)/3)
#+end_src
#+RESULTS:
Then, will first evaluate all the MOs at the grid points, and then we will
compute the overlap between all the MOs.
* Fortran
** Checking errors
All QMCkl functions return an error code. A convenient way to handle
errors is to write an error-checking function that displays the
error in text format and exits the program.
#+NAME: qmckl_check_error
#+begin_src f90
subroutine qmckl_check_error(rc, message) subroutine qmckl_check_error(rc, message)
use qmckl use qmckl
implicit none implicit none
@ -27,28 +134,28 @@ subroutine qmckl_check_error(rc, message)
call exit(rc) call exit(rc)
end if end if
end subroutine qmckl_check_error end subroutine qmckl_check_error
#+end_src #+end_src
* Computing an atomic orbital on a grid ** Computing an atomic orbital on a grid
:PROPERTIES: :PROPERTIES:
:header-args: :tangle ao_grid.f90 :header-args: :tangle ao_grid.f90
:END: :END:
The following program, in Fortran, computes the values of an atomic The following program, in Fortran, computes the values of an atomic
orbital on a regular 3-dimensional grid. The 100^3 grid points are orbital on a regular 3-dimensional grid. The 100^3 grid points are
automatically defined, such that the molecule fits in a box with 5 automatically defined, such that the molecule fits in a box with 5
atomic units in the borders. atomic units in the borders.
This program uses the ~qmckl_check_error~ function defined above. This program uses the ~qmckl_check_error~ function defined above.
To use this program, run To use this program, run
#+begin_src bash :tangle no #+begin_src bash :tangle no
$ ao_grid <trexio_file> <AO_id> <point_num> $ ao_grid <trexio_file> <AO_id> <point_num>
#+end_src #+end_src
#+begin_src f90 :noweb yes #+begin_src f90 :noweb yes
<<qmckl_check_error>> <<qmckl_check_error>>
program ao_grid program ao_grid
@ -73,11 +180,11 @@ program ao_grid
double precision :: rmin(3), rmax(3) double precision :: rmin(3), rmax(3)
double precision, allocatable :: points(:,:) double precision, allocatable :: points(:,:)
double precision, allocatable :: ao_vgl(:,:,:) double precision, allocatable :: ao_vgl(:,:,:)
#+end_src #+end_src
Start by fetching the command-line arguments: Start by fetching the command-line arguments:
#+begin_src f90 #+begin_src f90
if (iargc() /= 3) then if (iargc() /= 3) then
print *, 'Syntax: ao_grid <trexio_file> <AO_id> <point_num>' print *, 'Syntax: ao_grid <trexio_file> <AO_id> <point_num>'
call exit(-1) call exit(-1)
@ -92,21 +199,21 @@ program ao_grid
print *, 'Error: 0 < point_num < 300' print *, 'Error: 0 < point_num < 300'
call exit(-1) call exit(-1)
end if end if
#+end_src #+end_src
Create the QMCkl context and initialize it with the wave function Create the QMCkl context and initialize it with the wave function
present in the TREXIO file: present in the TREXIO file:
#+begin_src f90 #+begin_src f90
qmckl_ctx = qmckl_context_create() qmckl_ctx = qmckl_context_create()
rc = qmckl_trexio_read(qmckl_ctx, trexio_filename, 1_8*len(trim(trexio_filename))) rc = qmckl_trexio_read(qmckl_ctx, trexio_filename, 1_8*len(trim(trexio_filename)))
call qmckl_check_error(rc, 'Read TREXIO') call qmckl_check_error(rc, 'Read TREXIO')
#+end_src #+end_src
We need to check that ~ao_id~ is in the range, so we get the total We need to check that ~ao_id~ is in the range, so we get the total
number of AOs from QMCkl: number of AOs from QMCkl:
#+begin_src f90 #+begin_src f90
rc = qmckl_get_ao_basis_ao_num(qmckl_ctx, ao_num) rc = qmckl_get_ao_basis_ao_num(qmckl_ctx, ao_num)
call qmckl_check_error(rc, 'Getting ao_num') call qmckl_check_error(rc, 'Getting ao_num')
@ -114,24 +221,24 @@ program ao_grid
print *, 'Error: 0 < ao_id < ', ao_num print *, 'Error: 0 < ao_id < ', ao_num
call exit(-1) call exit(-1)
end if end if
#+end_src #+end_src
Now we will compute the limits of the box in which the molecule fits. Now we will compute the limits of the box in which the molecule fits.
For that, we first need to ask QMCkl the coordinates of nuclei. For that, we first need to ask QMCkl the coordinates of nuclei.
#+begin_src f90 #+begin_src f90
rc = qmckl_get_nucleus_num(qmckl_ctx, nucl_num) rc = qmckl_get_nucleus_num(qmckl_ctx, nucl_num)
call qmckl_check_error(rc, 'Get nucleus num') call qmckl_check_error(rc, 'Get nucleus num')
allocate( nucl_coord(3, nucl_num) ) allocate( nucl_coord(3, nucl_num) )
rc = qmckl_get_nucleus_coord(qmckl_ctx, 'N', nucl_coord, 3_8*nucl_num) rc = qmckl_get_nucleus_coord(qmckl_ctx, 'N', nucl_coord, 3_8*nucl_num)
call qmckl_check_error(rc, 'Get nucleus coord') call qmckl_check_error(rc, 'Get nucleus coord')
#+end_src #+end_src
We now compute the coordinates of opposite points of the box, and We now compute the coordinates of opposite points of the box, and
the distance between points along the 3 directions: the distance between points along the 3 directions:
#+begin_src f90 #+begin_src f90
rmin(1) = minval( nucl_coord(1,:) ) - 5.d0 rmin(1) = minval( nucl_coord(1,:) ) - 5.d0
rmin(2) = minval( nucl_coord(2,:) ) - 5.d0 rmin(2) = minval( nucl_coord(2,:) ) - 5.d0
rmin(3) = minval( nucl_coord(3,:) ) - 5.d0 rmin(3) = minval( nucl_coord(3,:) ) - 5.d0
@ -141,12 +248,12 @@ program ao_grid
rmax(3) = maxval( nucl_coord(3,:) ) + 5.d0 rmax(3) = maxval( nucl_coord(3,:) ) + 5.d0
dr(1:3) = (rmax(1:3) - rmin(1:3)) / dble(point_num_x-1) dr(1:3) = (rmax(1:3) - rmin(1:3)) / dble(point_num_x-1)
#+end_src #+end_src
We now produce the list of point coordinates where the AO will be We now produce the list of point coordinates where the AO will be
evaluated: evaluated:
#+begin_src f90 #+begin_src f90
point_num = point_num_x**3 point_num = point_num_x**3
allocate( points(point_num, 3) ) allocate( points(point_num, 3) )
ipoint=0 ipoint=0
@ -166,34 +273,35 @@ program ao_grid
end do end do
z = z + dr(3) z = z + dr(3)
end do end do
#+end_src #+end_src
We give the points to QMCkl: We give the points to QMCkl:
#+begin_src f90 #+begin_src f90
rc = qmckl_set_point(qmckl_ctx, 'T', points, point_num) rc = qmckl_set_point(qmckl_ctx, 'T', points, point_num)
call qmckl_check_error(rc, 'Setting points') call qmckl_check_error(rc, 'Setting points')
#+end_src #+end_src
We allocate the space required to retrieve the values, gradients and We allocate the space required to retrieve the values, gradients and
Laplacian of all AOs, and ask to retrieve the values of the Laplacian of all AOs, and ask to retrieve the values of the
AOs computed at the point positions. AOs computed at the point positions.
#+begin_src f90 #+begin_src f90
allocate( ao_vgl(ao_num, 5, point_num) ) allocate( ao_vgl(ao_num, 5, point_num) )
rc = qmckl_get_ao_basis_ao_vgl(qmckl_ctx, ao_vgl, ao_num*5_8*point_num) rc = qmckl_get_ao_basis_ao_vgl(qmckl_ctx, ao_vgl, ao_num*5_8*point_num)
call qmckl_check_error(rc, 'Setting points') call qmckl_check_error(rc, 'Setting points')
#+end_src #+end_src
We finally print the value of the AO: We finally print the value of the AO:
#+begin_src f90 #+begin_src f90
do ipoint=1, point_num do ipoint=1, point_num
print '(3(F16.10,X),E20.10)', points(ipoint, 1:3), ao_vgl(ao_id,1,ipoint) print '(3(F16.10,X),E20.10)', points(ipoint, 1:3), ao_vgl(ao_id,1,ipoint)
end do end do
#+end_src #+end_src
#+begin_src f90 #+begin_src f90
deallocate( nucl_coord, points, ao_vgl ) deallocate( nucl_coord, points, ao_vgl )
end program ao_grid end program ao_grid
#+end_src #+end_src

View File

@ -1289,7 +1289,7 @@ end function qmckl_compute_local_energy_f
double local_energy[chbrclf_walk_num]; double local_energy[chbrclf_walk_num];
rc = qmckl_get_local_energy(context, &(local_energy[0]), walk_num); rc = qmckl_get_local_energy(context, &(local_energy[0]), chbrclf_walk_num);
assert (rc == QMCKL_SUCCESS); assert (rc == QMCKL_SUCCESS);
#+end_src #+end_src