ETSF_IO library - documentation pages

### TABLE OF CONTENTS

- read_write_sub_access

## 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