TABLE OF CONTENTS


read_write_sub_access

[ Top ] [ etsf_io_tutorials ] [ Tutorials ]

NAME

read_write_sub_access

FUNCTION

In this example, we will describe how to read or write sub part of arrays. For example, to write the wavefunction each k point per k point, we need to use the wfs_pw__kpoint_access. This tutorial will show how to use all this kind of <varname>__something_access attributes existing in the different groups (see etsf_main for instance).

To compile this exemple, use (assuming default installation paths):

   ${F90} -I/opt/include/${F90} -o read_write_sub_access read_write_sub_access.f90
          -L/opt/lib -letsf_io -letsf_io_utils -L/usr/lib -lnetcdf

SOURCE

program read_write_sub_access

  use etsf_io
  use etsf_io_tools

  integer :: i, i_kpt, ncid

NOTES

All groups than contain arrays that can have a sub access (on spin or on k points) have attributes built on the following scheme:

   <short_variable_name>__[spin|kpoint]_access

When all spin or k points values must be read or write at once, one can let the default value (etsf_no_sub_access) ; but if one want to read or write only one spin or one k point, one should put the desired value in this attribute.

All this tutorial is oriented for writing, but it can be adapted easily for reading.

In the beginning of this tutorial, we define an ETSF file with 2 kpoints. This file will contain the kpoints group (etsf_kpoints), the group of wave data (etsf_basisdata) and the main group (etsf_main) with only the coefficient_of_wavefunctions array.

As shown in the first tutorial (create_a_crystal_den_file), the classical status variable lstat and error_data are created.

SOURCE

  logical                 :: lstat
  type(etsf_io_low_error) :: error_data

  ! Specific variables required by the library
  type(etsf_groups_flags) :: flags
  type(etsf_dims)         :: dims
  type(etsf_kpoints)      :: kpoints
  type(etsf_basisdata)    :: basisdata
  type(etsf_main)         :: main

NOTES

The following variables are used in the main program to store the informations. The pointers in the library will be used to point on them. Only some parts of each group will be used.

   * coef_pw: is a two dimensional array that store all the coefficients of
   plane waves, but only for one k point.
   * red_coord_pw_k: is a two dimensional array that stores the coordinates of plane
   waves for each band, but restricted on one k point.

SOURCE

  ! Variables that are declared in the main program in a real case
  double precision, allocatable, target :: coef_pw_k(:, :)
  ! Variables that will be used in the basisdata group.
  integer, allocatable, target          :: number_of_coefficients(:)
  integer, allocatable, target          :: red_coord_pw_k(:, :)
  ! Variables that will be used in the kpoints group.
  double precision, allocatable, target :: red_coord_kpt(:, :)
  double precision, allocatable, target :: kpoint_weights(:)
  ! Variable to store the definition of the basis set
  character(len = etsf_charlen), target :: basis

NOTES

We set the dimension (2 k points, no spin, 5 bands and 100 planewave coefficients).

SOURCE

  dims%max_number_of_coefficients = 100
  dims%max_number_of_states = 5
  dims%number_of_kpoints = 2
  dims%number_of_spinor_components = 1
  dims%number_of_spins = 1
  dims%real_or_complex_coefficients = 2

NOTES

As in the first tutorial (create_a_crystal_den_file), we use the high level routine etsf_io_data_init to define all dimensions and variables for the file we want to create.

In that case, we will use a precise definition of variables, not creating all variables of each included groups. For instance, the basis set will be limited to the required variables for a plane wave description.

SOURCE

  flags%basisdata = etsf_basisdata_basis_set + &
       & etsf_basisdata_red_coord_pw + &
       & etsf_basisdata_n_coeff
  flags%kpoints   = etsf_kpoints_red_coord_kpt + etsf_kpoints_kpoint_weights
  flags%main      = etsf_main_wfs_coeff
  call etsf_io_data_init("read_write_sub_access.nc", flags, dims, &
                       & "Tutorial ETSF_IO, use sub access to read or write", &
                       & "Created by the tutorial example of the library", &
                       & lstat, error_data)
  if (.not. lstat) then
    call etsf_io_low_error_handle(error_data)
    stop
  end if

NOTES

At this time of the example, the disk space to store the wave-function informations has been reserved. In a real case, we let the main program computing the plane waves and the arrays that describe them.

SOURCE

  write(basis, "(A)") "plane_waves"

  ! The main program allocate memory for its computation.
  allocate(coef_pw_k(2, dims%max_number_of_coefficients * dims%max_number_of_states))
  allocate(number_of_coefficients(dims%number_of_kpoints))
  allocate(red_coord_pw_k(3, dims%max_number_of_coefficients))
  allocate(red_coord_kpt(3, dims%number_of_kpoints))
  allocate(kpoint_weights(dims%number_of_kpoints))
  
  ! The main program compute all coordinates for k points and plane waves...
  red_coord_kpt = reshape( (/ 0.0d0, 0.0d0, 0.0d0, &
                            & 0.5d0, 0.5d0, 0.5d0 /), (/ 3, 2 /))
  kpoint_weights = (/ 0.5d0, 0.5d0 /)
  number_of_coefficients = (/ dims%max_number_of_coefficients, &
       & dims%max_number_of_coefficients /)

NOTES

To read or write with sub access, there is no high level routine such as etsf_io_data_write(). Then, we need to open the file and set it a write state. The way to open a file for writing is to use the routine etsf_io_low_open_modify() and then to call etsf_io_low_set_write_mode(). The first call will check that the header is correct.

When the file is not needed anymore, the ncid id must be released and the file closed, using etsf_io_low_close(). This is mandatory because without this call the write action may be not done.

SOURCE

  ! Open file for writing
  call etsf_io_low_open_modify(ncid, "read_write_sub_access.nc", &
       & lstat, error_data = error_data)
  if (.not. lstat) then
    call etsf_io_low_error_handle(error_data)
    stop
  end if
  
  ! We switch to write mode.
  call etsf_io_low_set_write_mode(ncid, lstat, error_data = error_data)
  if (.not. lstat) then
    call etsf_io_low_error_handle(error_data)
    stop
  end if

NOTES

We begin the big loop on k points. In this loop, the main program will compute the plane waves and the coordinates of the coefficients. Then, it will use the library to write the values for the current k point.

SOURCE

  do i_kpt = 1, dims%number_of_kpoints, 1
     ! We compute the plane wave coefficient with the famous
     ! algorithm that works well.
     do i = 1, dims%max_number_of_coefficients, 1
        red_coord_pw_k(:, i) = (/ -i, 0, i /)
     end do
     coef_pw_k(1, :) = (/ (i, i = 1, &
          & dims%max_number_of_coefficients * dims%max_number_of_states) /)
     coef_pw_k(2, :) = (/ (-i, i = 1, &
          & dims%max_number_of_coefficients * dims%max_number_of_states) /)

NOTES

We associate the pointers of groups we want to write with the data in memory.

SOURCE

     ! We associate the data
     main%coefficients_of_wavefunctions%data2D => coef_pw_k
     ! We set the sub access.
     main%wfs_coeff__kpoint_access = i_kpt
     ! Idem for the reduced coordinates of coefficients.
     basisdata%reduced_coordinates_of_plane_waves%data2D => red_coord_pw_k
     basisdata%red_coord_pw__kpoint_access = i_kpt

NOTES

Now that all the arrays we want to write are associated, we can call the write routine. This routine will read automatically the <var>__kpoint_access attribute and will check the dimensions of the associated arrays.

SOURCE

     ! We use the group level write routine.
     call etsf_io_main_put(ncid, main, lstat, error_data)
     if (.not. lstat) then
        call etsf_io_low_error_handle(error_data)
        stop
     end if
     call etsf_io_basisdata_put(ncid, basisdata, lstat, error_data)
     if (.not. lstat) then
        call etsf_io_low_error_handle(error_data)
        stop
     end if

     ! End of the kpoint big loop.
  end do

NOTES

We write the other data that are independent of the kpoint loop.

WARNINGS

It is important to associate to nullify the already used pointers to avoid to write them again.

SOURCE

  ! We set the associations.
  kpoints%reduced_coordinates_of_kpoints => red_coord_kpt
  kpoints%kpoint_weights => kpoint_weights
  basisdata%basis_set => basis
  basisdata%reduced_coordinates_of_plane_waves%data2D => null()
  basisdata%number_of_coefficients => number_of_coefficients
  ! We call the group level write routines.
  call etsf_io_kpoints_put(ncid, kpoints, lstat, error_data)
  if (.not. lstat) then
     call etsf_io_low_error_handle(error_data)
     stop
  end if
  call etsf_io_basisdata_put(ncid, basisdata, lstat, error_data)
  if (.not. lstat) then
     call etsf_io_low_error_handle(error_data)
     stop
  end if

NOTES

We then set the use_time_reversal_at_gamma attribute for this file using the etsf_io_tools module. We write it after the other data since the routine will check that the basis set is indeed a plane wave one and the two variables impacted by this attributes must already exist.

SOURCE

  call etsf_io_tools_set_time_reversal_symmetry(ncid, .false., lstat, error_data)
  ! We handle the error
  if (.not. lstat) then
    call etsf_io_low_error_handle(error_data)
    stop
  end if

NOTES

As said before, we need to close the file.

SOURCE

  ! We close the file.
  call etsf_io_low_close(ncid, lstat, error_data)
  ! We handle the error
  if (.not. lstat) then
    call etsf_io_low_error_handle(error_data)
    stop
  end if
  
  ! The main program will deallocate its own memory.
  deallocate(coef_pw_k)
  deallocate(number_of_coefficients)
  deallocate(red_coord_pw_k)
  deallocate(red_coord_kpt)
  deallocate(kpoint_weights)
end program read_write_sub_access