2021-12-16 00:11:36 +01:00
|
|
|
#+TITLE: Examples
|
|
|
|
#+STARTUP: latexpreview
|
2023-02-17 17:41:36 +01:00
|
|
|
#+SETUPFILE: ./theme.setup
|
2021-12-16 00:11:36 +01:00
|
|
|
|
2023-02-17 15:48:20 +01:00
|
|
|
* Writing nuclear coordinates
|
2021-12-16 00:11:36 +01:00
|
|
|
|
2023-02-17 15:48:20 +01:00
|
|
|
Here is a demonstration of how to use TREXIO to write the nuclear
|
|
|
|
coordinates of a water molecule to a file. It shows the basic steps
|
|
|
|
involved in opening a file, writing the data, and closing the file,
|
|
|
|
as well as the necessary TREXIO functions to perform these actions.
|
|
|
|
|
|
|
|
** C
|
|
|
|
#+begin_src c
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <trexio.h>
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
int num = 3; // Number of atoms
|
|
|
|
double coord[][3] = {
|
|
|
|
// xyz coordinates in atomic units
|
|
|
|
0. , 0. , -0.24962655,
|
|
|
|
0. , 2.70519714, 1.85136466,
|
|
|
|
0. , -2.70519714, 1.85136466 };
|
|
|
|
|
|
|
|
trexio_exit_code rc;
|
|
|
|
|
|
|
|
// Open the TREXIO file
|
|
|
|
trexio_t* f = trexio_open("water.trexio", 'w', TREXIO_HDF5, &rc);
|
|
|
|
if (rc != TREXIO_SUCCESS) {
|
|
|
|
fprintf(stderr, "Error: %s\n", trexio_string_of_error(rc));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the number of nuclei
|
|
|
|
rc = trexio_write_nucleus_num (f, num);
|
|
|
|
if (rc != TREXIO_SUCCESS) {
|
|
|
|
fprintf(stderr, "Error: %s\n", trexio_string_of_error(rc));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the nuclear coordinates
|
|
|
|
rc = trexio_write_nucleus_coord (f, &coord[0][0]);
|
|
|
|
if (rc != TREXIO_SUCCESS) {
|
|
|
|
fprintf(stderr, "Error: %s\n", trexio_string_of_error(rc));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close the TREXIO file
|
|
|
|
rc = trexio_close(f);
|
|
|
|
if (rc != TREXIO_SUCCESS) {
|
|
|
|
fprintf(stderr, "Error: %s\n", trexio_string_of_error(rc));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
** Python
|
|
|
|
|
|
|
|
This code uses the TREXIO Python binding to create a new TREXIO file named
|
|
|
|
=water.trexio=, and write the nuclear coordinates of a water molecule.
|
|
|
|
|
|
|
|
The ~coord~ variable is a list of three lists, each containing the x, y,
|
|
|
|
and z coordinates of the water molecule's nuclei.
|
|
|
|
|
|
|
|
The ~with~ statement is used to ensure the file is properly closed after
|
|
|
|
the write is complete.
|
|
|
|
|
|
|
|
The ~trexio.write_nucleus_num~ function is used to write the number of
|
|
|
|
nuclei in the system.
|
|
|
|
|
|
|
|
The ~trexio.write_nucleus_coord~ function is used to write the nuclear
|
|
|
|
coordinates of the system.
|
|
|
|
|
|
|
|
#+begin_src python
|
|
|
|
import trexio
|
|
|
|
coord = [ # xyz coordinates in atomic units
|
|
|
|
[0. , 0., -0.24962655],
|
|
|
|
[0. , 2.70519714, 1.85136466],
|
|
|
|
[0. , -2.70519714, 1.85136466]
|
|
|
|
]
|
|
|
|
# The Python API calls can raise `trexio.Error`
|
|
|
|
# exceptions to be handled via try/except clauses
|
|
|
|
# in the user application
|
|
|
|
with trexio.File("water.trexio", 'w',
|
|
|
|
back_end=trexio.TREXIO_HDF5) as f:
|
|
|
|
trexio.write_nucleus_num(f, len(coord))
|
|
|
|
trexio.write_nucleus_coord(f, coord)
|
|
|
|
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
** Fortran
|
|
|
|
#+begin_src f90
|
|
|
|
program trexio_water
|
|
|
|
use trexio
|
|
|
|
|
|
|
|
integer, parameter :: num=3 ! Number of nuclei
|
|
|
|
double precision :: coord(3,3) ! Array of atom coordinates
|
|
|
|
|
|
|
|
integer(trexio_t) :: f ! The TREXIO file handle
|
|
|
|
integer(trexio_exit_code) :: rc ! TREXIO return code
|
|
|
|
character*(128) :: err_msg ! String holding the error message
|
|
|
|
|
|
|
|
coord(:,:) = reshape( (/ 0.d0 , 0.d0 , -0.24962655d0, &
|
|
|
|
0.d0 , 2.70519714d0, 1.85136466d0, &
|
|
|
|
0.d0 , -2.70519714d0, 1.85136466d0 /), &
|
|
|
|
shape(coord) )
|
|
|
|
|
|
|
|
! Open the TREXIO file
|
|
|
|
f = trexio_open ('water.trexio', 'w', TREXIO_HDF5, rc)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error: '//trim(err_msg)
|
|
|
|
call exit(-1)
|
|
|
|
end if
|
|
|
|
|
|
|
|
! Write the number of nuclei
|
|
|
|
rc = trexio_write_nucleus_num (f, num)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error: '//trim(err_msg)
|
|
|
|
call exit(-1)
|
|
|
|
end if
|
|
|
|
|
|
|
|
! Write the nuclear coordinates
|
|
|
|
rc = trexio_write_nucleus_coord (f, coord)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error: '//trim(err_msg)
|
|
|
|
call exit(-1)
|
|
|
|
end if
|
|
|
|
|
|
|
|
! Close the TREXIO file
|
|
|
|
rc = trexio_close(f)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error: '//trim(err_msg)
|
|
|
|
call exit(-1)
|
|
|
|
end if
|
|
|
|
|
|
|
|
end program
|
|
|
|
#+end_src
|
|
|
|
|
2022-06-27 17:15:27 +02:00
|
|
|
* Accessing sparse quantities (integrals)
|
|
|
|
|
2021-12-16 00:11:36 +01:00
|
|
|
** Fortran
|
|
|
|
:PROPERTIES:
|
|
|
|
:header-args: :tangle print_energy.f90
|
|
|
|
:END:
|
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
program print_energy
|
|
|
|
use trexio
|
|
|
|
implicit none
|
|
|
|
|
|
|
|
character*(128) :: filename ! Name of the input file
|
|
|
|
integer :: rc ! Return code for error checking
|
|
|
|
integer(8) :: f ! TREXIO file handle
|
|
|
|
character*(128) :: err_msg ! Error message
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
This program computes the energy as:
|
|
|
|
|
|
|
|
\[
|
2022-01-10 10:25:18 +01:00
|
|
|
E = E_{\text{NN}} + \sum_{ij} \gamma_{ij}\, \langle j | h | i \rangle\,
|
|
|
|
+\, \frac{1}{2} \sum_{ijkl} \Gamma_{ijkl}\, \langle k l | i j
|
2021-12-16 00:11:36 +01:00
|
|
|
\rangle\; \textrm{ with } \; 0 < i,j,k,l \le n
|
|
|
|
\]
|
|
|
|
One needs to read from the TREXIO file:
|
|
|
|
|
|
|
|
- $n$ :: The number of molecular orbitals
|
|
|
|
- $E_{\text{NN}}$ :: The nuclear repulsion energy
|
2022-01-10 10:25:18 +01:00
|
|
|
- $\gamma_{ij}$ :: The one-body reduced density matrix
|
|
|
|
- $\langle j |h| i \rangle$ :: The one-electron Hamiltonian integrals
|
2021-12-16 00:11:36 +01:00
|
|
|
- $\Gamma_{ijkl}$ :: The two-body reduced density matrix
|
2022-01-10 10:25:18 +01:00
|
|
|
- $\langle k l | i j \rangle$ :: The electron repulsion integrals
|
|
|
|
|
2021-12-16 00:11:36 +01:00
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
integer :: n
|
|
|
|
double precision :: E, E_nn
|
|
|
|
double precision, allocatable :: D(:,:), h0(:,:)
|
|
|
|
double precision, allocatable :: G(:,:,:,:), W(:,:,:,:)
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Declare Temporary variables
|
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
integer :: i, j, k, l, m
|
2021-12-17 11:03:09 +01:00
|
|
|
integer(8), parameter :: BUFSIZE = 100000_8
|
2021-12-16 00:11:36 +01:00
|
|
|
integer(8) :: offset, icount, size_max
|
|
|
|
integer :: buffer_index(4,BUFSIZE)
|
|
|
|
double precision :: buffer_values(BUFSIZE)
|
|
|
|
|
|
|
|
double precision, external :: ddot ! BLAS dot product
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Obtain the name of the TREXIO file from the command line, and open it for reading
|
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
call getarg(1, filename)
|
|
|
|
|
2023-05-05 08:30:01 +02:00
|
|
|
f = trexio_open (filename, 'r', TREXIO_AUTO, rc)
|
2021-12-16 00:11:36 +01:00
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error opening TREXIO file: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Read the nuclear repulsion energy
|
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
rc = trexio_read_nucleus_repulsion(f, E_nn)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error reading nuclear repulsion: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Read the number of molecular orbitals
|
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
rc = trexio_read_mo_num(f, n)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error reading number of MOs: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Allocate memory
|
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
allocate( D(n,n), h0(n,n) )
|
|
|
|
allocate( G(n,n,n,n), W(n,n,n,n) )
|
2021-12-17 11:03:09 +01:00
|
|
|
G(:,:,:,:) = 0.d0
|
|
|
|
W(:,:,:,:) = 0.d0
|
2021-12-16 00:11:36 +01:00
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Read one-electron quantities
|
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
rc = trexio_has_mo_1e_int_core_hamiltonian(f)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
stop 'No core hamiltonian in file'
|
|
|
|
end if
|
|
|
|
|
|
|
|
rc = trexio_read_mo_1e_int_core_hamiltonian(f, h0)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error reading core Hamiltonian: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
|
|
|
|
|
|
|
|
|
|
|
rc = trexio_has_rdm_1e(f)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
stop 'No 1e RDM in file'
|
|
|
|
end if
|
|
|
|
|
|
|
|
rc = trexio_read_rdm_1e(f, D)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error reading one-body RDM: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Read two-electron quantities
|
|
|
|
|
2021-12-17 11:03:09 +01:00
|
|
|
Reading is done with OpenMP. Each thread reads its own buffer, and
|
|
|
|
the buffers are then processed in parallel.
|
|
|
|
|
|
|
|
Reading the file requires a lock, so it is done in a critical
|
|
|
|
section. The ~offset~ variable is shared, and it is incremented in
|
|
|
|
the critical section. For each read, the function returns in
|
|
|
|
~icount~ the number of read integrals, so this variable needs also
|
|
|
|
to be protected in the critical section when modified.
|
|
|
|
|
|
|
|
**** Electron repulsion integrals
|
|
|
|
|
|
|
|
#+begin_src f90
|
2021-12-16 00:11:36 +01:00
|
|
|
rc = trexio_has_mo_2e_int_eri(f)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
stop 'No electron repulsion integrals in file'
|
|
|
|
end if
|
2021-12-17 11:03:09 +01:00
|
|
|
|
2021-12-16 00:11:36 +01:00
|
|
|
rc = trexio_read_mo_2e_int_eri_size (f, size_max)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error reading number of ERIs: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
|
|
|
|
|
|
|
offset = 0_8
|
2021-12-17 11:03:09 +01:00
|
|
|
!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(icount, i, j, k, l, &
|
|
|
|
!$OMP buffer_index, buffer_values, m)
|
|
|
|
icount = BUFSIZE
|
|
|
|
do while (icount == BUFSIZE)
|
|
|
|
!$OMP CRITICAL
|
|
|
|
if (offset < size_max) then
|
|
|
|
rc = trexio_read_mo_2e_int_eri(f, offset, icount, buffer_index, buffer_values)
|
|
|
|
offset = offset + icount
|
|
|
|
else
|
|
|
|
icount = 0
|
|
|
|
end if
|
|
|
|
!$OMP END CRITICAL
|
|
|
|
do m=1,icount
|
2021-12-16 00:11:36 +01:00
|
|
|
i = buffer_index(1,m)
|
|
|
|
j = buffer_index(2,m)
|
|
|
|
k = buffer_index(3,m)
|
|
|
|
l = buffer_index(4,m)
|
|
|
|
W(i,j,k,l) = buffer_values(m)
|
|
|
|
W(k,j,i,l) = buffer_values(m)
|
|
|
|
W(i,l,k,j) = buffer_values(m)
|
|
|
|
W(k,l,i,j) = buffer_values(m)
|
|
|
|
W(j,i,l,k) = buffer_values(m)
|
|
|
|
W(j,k,l,i) = buffer_values(m)
|
|
|
|
W(l,i,j,k) = buffer_values(m)
|
|
|
|
W(l,k,j,i) = buffer_values(m)
|
|
|
|
end do
|
|
|
|
end do
|
2021-12-17 11:03:09 +01:00
|
|
|
!$OMP END PARALLEL
|
|
|
|
#+end_src
|
2021-12-16 00:11:36 +01:00
|
|
|
|
2021-12-17 11:03:09 +01:00
|
|
|
**** Reduced density matrix
|
|
|
|
|
|
|
|
#+begin_src f90
|
2021-12-16 00:11:36 +01:00
|
|
|
rc = trexio_has_rdm_2e(f)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
stop 'No two-body density matrix in file'
|
|
|
|
end if
|
|
|
|
|
|
|
|
rc = trexio_read_rdm_2e_size (f, size_max)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error reading number of 2-RDM elements: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
|
|
|
|
|
|
|
offset = 0_8
|
2021-12-17 11:03:09 +01:00
|
|
|
!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(icount, i, j, k, l, &
|
|
|
|
!$OMP buffer_index, buffer_values, m)
|
|
|
|
icount = bufsize
|
2021-12-16 00:11:36 +01:00
|
|
|
do while (offset < size_max)
|
2021-12-17 11:03:09 +01:00
|
|
|
!$OMP CRITICAL
|
|
|
|
if (offset < size_max) then
|
|
|
|
rc = trexio_read_rdm_2e(f, offset, icount, buffer_index, buffer_values)
|
|
|
|
offset = offset + icount
|
|
|
|
else
|
|
|
|
icount = 0
|
|
|
|
end if
|
|
|
|
!$OMP END CRITICAL
|
|
|
|
do m=1,icount
|
2021-12-16 00:11:36 +01:00
|
|
|
i = buffer_index(1,m)
|
|
|
|
j = buffer_index(2,m)
|
|
|
|
k = buffer_index(3,m)
|
|
|
|
l = buffer_index(4,m)
|
|
|
|
G(i,j,k,l) = buffer_values(m)
|
|
|
|
end do
|
|
|
|
end do
|
2021-12-17 11:03:09 +01:00
|
|
|
!$OMP END PARALLEL
|
|
|
|
|
|
|
|
#+end_src
|
2021-12-16 00:11:36 +01:00
|
|
|
|
|
|
|
*** Compute the energy
|
|
|
|
|
2022-01-10 10:25:18 +01:00
|
|
|
When the orbitals are real, we can use
|
|
|
|
\begin{eqnarray*}
|
|
|
|
E &=& E_{\text{NN}} + \sum_{ij} \gamma_{ij}\, \langle j | h | i \rangle\,
|
|
|
|
+\, \frac{1}{2} \sum_{ijkl} \Gamma_{ijkl}\, \langle k l | i j
|
|
|
|
\rangle \\
|
|
|
|
&=& E_{\text{NN}} + \sum_{ij} \gamma_{ij}\, \langle i | h | j \rangle\,
|
|
|
|
+\, \frac{1}{2} \sum_{ijkl} \Gamma_{ijkl}\, \langle i j | k l
|
|
|
|
\rangle \\
|
|
|
|
\end{eqnarray*}
|
|
|
|
|
|
|
|
As $(n,m)$ 2D arrays are stored in memory as $(n \times m)$ 1D
|
2021-12-17 11:03:09 +01:00
|
|
|
arrays, we could pass the matrices to the ~ddot~ BLAS function to
|
|
|
|
perform the summations in a single call for the 1-electron quantities.
|
|
|
|
Instead, we prefer to interleave the 1-electron (negative) and
|
|
|
|
2-electron (positive) summations to have a better cancellation of
|
|
|
|
numerical errors.
|
|
|
|
|
|
|
|
Here $n^4$ can be larger than the largest possible 32-bit integer,
|
|
|
|
so it is not safe to pass $n^4$ to the ~ddot~ BLAS
|
|
|
|
function. Hence, we perform $n^2$ loops, using vectors of size $n^2$.
|
|
|
|
|
2021-12-16 00:11:36 +01:00
|
|
|
#+begin_src f90
|
2021-12-17 11:03:09 +01:00
|
|
|
|
|
|
|
E = 0.d0
|
|
|
|
do l=1,n
|
|
|
|
E = E + ddot( n, D(1,l), 1, h0(1,l), 1 )
|
|
|
|
do k=1,n
|
|
|
|
E = E + 0.5d0 * ddot( n*n, G(1,1,k,l), 1, W(1,1,k,l), 1 )
|
|
|
|
end do
|
|
|
|
end do
|
|
|
|
E = E + E_nn
|
2021-12-16 00:11:36 +01:00
|
|
|
|
|
|
|
print *, 'Energy: ', E
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Terminate
|
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
deallocate( D, h0, G, W )
|
|
|
|
|
|
|
|
end program
|
|
|
|
#+end_src
|
2022-06-27 17:15:27 +02:00
|
|
|
|
2023-05-05 08:30:01 +02:00
|
|
|
** Python
|
|
|
|
:PROPERTIES:
|
|
|
|
:header-args: :tangle print_energy.py
|
|
|
|
:END:
|
|
|
|
|
|
|
|
#+begin_src python
|
|
|
|
import sys
|
|
|
|
import trexio
|
|
|
|
import numpy as np
|
|
|
|
|
|
|
|
BUFSIZE = 100000
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
This program computes the energy as:
|
|
|
|
|
|
|
|
\[
|
|
|
|
E = E_{\text{NN}} + \sum_{ij} \gamma_{ij}\, \langle j | h | i \rangle\,
|
|
|
|
+\, \frac{1}{2} \sum_{ijkl} \Gamma_{ijkl}\, \langle k l | i j
|
|
|
|
\rangle\; \textrm{ with } \; 0 < i,j,k,l \le n
|
|
|
|
\]
|
|
|
|
One needs to read from the TREXIO file:
|
|
|
|
|
|
|
|
- $n$ :: The number of molecular orbitals
|
|
|
|
- $E_{\text{NN}}$ :: The nuclear repulsion energy
|
|
|
|
- $\gamma_{ij}$ :: The one-body reduced density matrix
|
|
|
|
- $\langle j |h| i \rangle$ :: The one-electron Hamiltonian integrals
|
|
|
|
- $\Gamma_{ijkl}$ :: The two-body reduced density matrix
|
|
|
|
- $\langle k l | i j \rangle$ :: The electron repulsion integrals
|
|
|
|
|
|
|
|
*** Obtain the name of the TREXIO file from the command line, and open it for reading
|
|
|
|
|
|
|
|
#+begin_src python
|
|
|
|
filename = sys.argv[1]
|
|
|
|
f = trexio.File(filename, 'r', trexio.TREXIO_AUTO)
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Read the nuclear repulsion energy
|
|
|
|
|
|
|
|
#+begin_src python
|
|
|
|
E_nn = trexio.read_nucleus_repulsion(f)
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Read the number of molecular orbitals
|
|
|
|
|
|
|
|
#+begin_src python
|
|
|
|
n = trexio.read_mo_num(f)
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Read one-electron quantities
|
|
|
|
|
|
|
|
#+begin_src python
|
|
|
|
if not trexio.has_mo_1e_int_core_hamiltonian(f):
|
|
|
|
print("No core hamiltonian in file")
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
h0 = trexio.read_mo_1e_int_core_hamiltonian(f)
|
|
|
|
|
|
|
|
if not trexio.has_rdm_1e(f):
|
|
|
|
print("No 1e RDM in file")
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
D = trexio.read_rdm_1e(f)
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Read two-electron quantities
|
|
|
|
|
|
|
|
**** Electron repulsion integrals
|
|
|
|
|
|
|
|
#+begin_src python
|
|
|
|
if not trexio.has_mo_2e_int_eri(f):
|
|
|
|
print("No electron repulsion integrals in file")
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
size_max = trexio.read_mo_2e_int_eri_size(f)
|
|
|
|
|
|
|
|
offset = 0
|
|
|
|
icount = BUFSIZE
|
|
|
|
feof = False
|
|
|
|
W = np.zeros( (n,n,n,n) )
|
|
|
|
while not feof:
|
|
|
|
buffer_index, buffer_values, icount, feof = trexio.read_mo_2e_int_eri(f, offset, icount)
|
|
|
|
for m in range(icount):
|
|
|
|
i, j, k, l = buffer_index[m]
|
|
|
|
W[i,j,k,l] = buffer_values[m]
|
|
|
|
W[k,j,i,l] = buffer_values[m]
|
|
|
|
W[i,l,k,j] = buffer_values[m]
|
|
|
|
W[k,l,i,j] = buffer_values[m]
|
|
|
|
W[j,i,l,k] = buffer_values[m]
|
|
|
|
W[j,k,l,i] = buffer_values[m]
|
|
|
|
W[l,i,j,k] = buffer_values[m]
|
|
|
|
W[l,k,j,i] = buffer_values[m]
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
**** Reduced density matrix
|
|
|
|
|
|
|
|
#+begin_src python
|
|
|
|
if not trexio.has_rdm_2e(f):
|
|
|
|
print("No two-body density matrix in file")
|
|
|
|
|
|
|
|
offset = 0
|
|
|
|
icount = BUFSIZE
|
|
|
|
feof = False
|
|
|
|
G = np.zeros( (n,n,n,n) )
|
|
|
|
while not feof:
|
|
|
|
buffer_index, buffer_values, icount, feof = trexio.read_rdm_2e(f, offset, icount)
|
|
|
|
for m in range(icount):
|
|
|
|
i, j, k, l = buffer_index[m]
|
|
|
|
G[i,j,k,l] = buffer_values[m]
|
|
|
|
|
|
|
|
#+end_src
|
|
|
|
|
|
|
|
*** Compute the energy
|
|
|
|
|
|
|
|
When the orbitals are real, we can use
|
|
|
|
\begin{eqnarray*}
|
|
|
|
E &=& E_{\text{NN}} + \sum_{ij} \gamma_{ij}\, \langle j | h | i \rangle\,
|
|
|
|
+\, \frac{1}{2} \sum_{ijkl} \Gamma_{ijkl}\, \langle k l | i j
|
|
|
|
\rangle \\
|
|
|
|
&=& E_{\text{NN}} + \sum_{ij} \gamma_{ij}\, \langle i | h | j \rangle\,
|
|
|
|
+\, \frac{1}{2} \sum_{ijkl} \Gamma_{ijkl}\, \langle i j | k l
|
|
|
|
\rangle \\
|
|
|
|
\end{eqnarray*}
|
|
|
|
|
|
|
|
#+begin_src python
|
|
|
|
G = np.reshape(G, (n*n, n*n) )
|
|
|
|
W = np.reshape(W, (n*n, n*n) )
|
|
|
|
E = E_nn
|
|
|
|
E += 0.5*sum( [ np.dot(G[:,l], W[:,l]) for l in range(n*n) ] )
|
|
|
|
E += sum( [ np.dot(D[:,l], h0[:,l]) for l in range(n) ] )
|
|
|
|
|
|
|
|
print (f"Energy: {E}")
|
|
|
|
#+end_src
|
|
|
|
|
2022-06-27 17:15:27 +02:00
|
|
|
* Reading determinants
|
2023-02-17 15:48:20 +01:00
|
|
|
|
2022-06-27 17:15:27 +02:00
|
|
|
** Fortran
|
|
|
|
:PROPERTIES:
|
|
|
|
:header-args: :tangle print_dets.f90
|
|
|
|
:END:
|
|
|
|
|
|
|
|
#+begin_src f90
|
|
|
|
program test
|
|
|
|
|
|
|
|
use trexio
|
|
|
|
implicit none
|
|
|
|
|
2022-06-28 10:15:38 +02:00
|
|
|
character*(128) :: filename ! Name of the input file
|
|
|
|
integer(trexio_exit_code) :: rc ! Return code for error checking
|
|
|
|
integer(trexio_t) :: trex_determinant_file ! TREXIO file handle
|
|
|
|
character*(128) :: err_msg ! Error message
|
2022-06-27 17:17:08 +02:00
|
|
|
|
2022-06-27 17:15:27 +02:00
|
|
|
|
|
|
|
integer*8, allocatable :: buffer(:,:,:)
|
|
|
|
integer(8) :: offset, icount, BUFSIZE
|
|
|
|
integer :: ndet, int64_num, m
|
|
|
|
|
|
|
|
integer :: occ_num_up, occ_num_dn
|
|
|
|
integer, allocatable :: orb_list_up(:), orb_list_dn(:)
|
|
|
|
|
|
|
|
call getarg(1, filename)
|
|
|
|
|
|
|
|
trex_determinant_file = trexio_open(filename, 'r', TREXIO_AUTO, rc)
|
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error opening TREXIO file: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
|
|
|
|
|
|
|
rc = trexio_read_determinant_num(trex_determinant_file, ndet)
|
2022-06-28 10:15:38 +02:00
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error reading determinant_num: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
2022-06-27 17:15:27 +02:00
|
|
|
print *, 'ndet', ndet
|
|
|
|
|
|
|
|
rc = trexio_get_int64_num(trex_determinant_file, int64_num)
|
2022-06-28 10:15:38 +02:00
|
|
|
if (rc /= TREXIO_SUCCESS) then
|
|
|
|
call trexio_string_of_error(rc, err_msg)
|
|
|
|
print *, 'Error reading int64_num: '//trim(err_msg)
|
|
|
|
stop
|
|
|
|
end if
|
2022-06-27 17:15:27 +02:00
|
|
|
print *, 'int64_num', int64_num
|
|
|
|
|
|
|
|
BUFSIZE = 1000_8
|
|
|
|
allocate(buffer(int64_num, 2, BUFSIZE))
|
|
|
|
allocate(orb_list_up(int64_num*64), orb_list_dn(int64_num*64))
|
|
|
|
|
|
|
|
offset = 0_8
|
|
|
|
icount = BUFSIZE
|
|
|
|
do while (icount == BUFSIZE)
|
|
|
|
if (offset < ndet) then
|
|
|
|
rc = trexio_read_determinant_list(trex_determinant_file, offset, icount, buffer)
|
|
|
|
offset = offset + icount
|
|
|
|
else
|
|
|
|
icount = 0
|
|
|
|
end if
|
|
|
|
print *, '---'
|
|
|
|
do m=1,icount
|
|
|
|
rc = trexio_to_orbital_list_up_dn(int64_num, buffer(1,1,m), &
|
|
|
|
orb_list_up, orb_list_dn, occ_num_up, occ_num_dn)
|
|
|
|
print '(100(I3,X))', (orb_list_up(1:occ_num_up)), (orb_list_dn(1:occ_num_dn))
|
|
|
|
print *, ''
|
|
|
|
end do
|
2022-06-28 10:15:38 +02:00
|
|
|
end do
|
|
|
|
|
|
|
|
deallocate(buffer, orb_list_dn, orb_list_up)
|
2022-06-27 17:15:27 +02:00
|
|
|
|
|
|
|
end
|
|
|
|
#+end_src
|
|
|
|
|