LCOV - code coverage report
Current view: top level - shared/common/src/27_toolbox_oop - m_nctk.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 74.6 % 614 458
Test Date: 2026-11-09 22:30:52 Functions: 81.8 % 44 36
Branches: 49.0 % 796 390

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_nctk
       2                 :             : !! NAME
       3                 :             : !! m_nctk
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  Tools and wrappers for NETCDF-IO.
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !!  Copyright (C) 2008-2026 ABINIT group (MG)
      10                 :             : !!  This file is distributed under the terms of the
      11                 :             : !!  GNU General Public License, see ~abinit/COPYING
      12                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13                 :             : !!
      14                 :             : !! TODO
      15                 :             : !!   Remove create_nc_file, write_var_netcdf, the output of OUT.nc is dangereous
      16                 :             : !!     because we can create too many dimensions and get
      17                 :             : !!    nf90_def_dim - NetCDF library returned:   NetCDF: NC_MAX_DIMS exceeded
      18                 :             : !!   Moreover the multiple calls to redef render the IO very inefficient
      19                 :             : !!   That part should be rationalized!
      20                 :             : !!
      21                 :             : !! SOURCE
      22                 :             : 
      23                 :             : #if defined HAVE_CONFIG_H
      24                 :             : #include "config.h"
      25                 :             : #endif
      26                 :             : 
      27                 :             : #include "abi_common.h"
      28                 :             : 
      29                 :             : MODULE m_nctk
      30                 :             : 
      31                 :             :  use, intrinsic :: iso_c_binding
      32                 :             :  use defs_basis
      33                 :             :  use m_abicore
      34                 :             :  use m_build_info
      35                 :             :  use m_errors
      36                 :             :  use m_xmpi
      37                 :             :  use netcdf
      38                 :             : 
      39                 :             :  use m_fstrings,  only : itoa, sjoin, lstrip, char_count, strcat, endswith, startswith, ltoa
      40                 :             :  use m_io_tools,  only : pick_aname, delete_file, file_exists
      41                 :             :  use m_yaml,      only : DTSET_IDX
      42                 :             : 
      43                 :             :  implicit none
      44                 :             : 
      45                 :             :  private
      46                 :             : !!***
      47                 :             : 
      48                 :             :  integer,public,parameter :: nctk_noid = -huge(1)
      49                 :             :  ! This value is used to signal to procedures that IO should not be performed.
      50                 :             : 
      51                 :             :  ! Basic variables
      52                 :             :  character(len=*),public,parameter :: etsfio_file_format = "ETSF Nanoquanta"
      53                 :             :  character(len=*),public,parameter :: etsfio_conventions = "http://www.etsf.eu/fileformats/"
      54                 :             : 
      55                 :             :  integer,public,parameter :: etsfio_charlen = abi_slen
      56                 :             :  ! The value corresponding to character_string_len
      57                 :             : 
      58                 :             :  real,public,parameter :: etsfio_version = 3.3
      59                 :             :  ! This is clearly wrong because one should use strings instad of floats that cannot be represented exactly
      60                 :             :  ! but, unfortunately, it's in the specifications and we have to live with it!
      61                 :             : 
      62                 :             :  integer,public,parameter :: nctk_max_dims = NF90_MAX_DIMS
      63                 :             :  ! Maximum number of dimensions
      64                 :             : 
      65                 :             :  integer,public,parameter :: nctk_slen = NF90_MAX_NAME
      66                 :             :  ! String length used for the names of dimensions and variables
      67                 :             :  ! The maximum allowable number of characters
      68                 :             : 
      69                 :             :  ! netcdf4-hdf5 is the default
      70                 :             :  integer,save,private :: def_cmode_for_seq_create = ior(ior(nf90_clobber, nf90_netcdf4), nf90_write)
      71                 :             :  ! netcdf4 classic
      72                 :             :  !integer,save,private :: def_cmode_for_seq_create = ior(nf90_clobber, nf90_write)
      73                 :             : 
      74                 :             :  character(len=5),private,parameter :: NCTK_IMPLICIT_DIMS(10) = [ &
      75                 :             :    "one  ", "two  ", "three", "four ", "five ", "six  ", "seven", "eight", "nine ", "ten  "]
      76                 :             : 
      77                 :             : !!****t* m_nctk/nctkerr_t
      78                 :             : !! NAME
      79                 :             : !! nctkerr_t
      80                 :             : !!
      81                 :             : !! FUNCTION
      82                 :             : !!
      83                 :             : !! SOURCE
      84                 :             : !!
      85                 :             :  type,private :: nctkerr_t
      86                 :             :    integer :: ncerr = nf90_noerr
      87                 :             :    integer :: line = 0
      88                 :             :    character(len=fnlen) :: file = "Dummy File"
      89                 :             :    character(len=2048) :: msg="No error detected"
      90                 :             :  end type nctkerr_t
      91                 :             : !!***
      92                 :             : 
      93                 :             :  type(nctkerr_t),private,save :: einfo
      94                 :             : 
      95                 :             : !!****t* m_nctk/ncfdim_t
      96                 :             : !! NAME
      97                 :             : !! nctkdim_t
      98                 :             : !!
      99                 :             : !! FUNCTION
     100                 :             : !!  Stores the name and the value of a netcdf dimension
     101                 :             : !!
     102                 :             : !! SOURCE
     103                 :             : 
     104                 :             :  type,public :: nctkdim_t
     105                 :             :    character(len=nctk_slen) :: name   ! name of the dimension.
     106                 :             :    integer :: value                   ! value of the dimension.
     107                 :             :    !integer :: id
     108                 :             :  end type nctkdim_t
     109                 :             : !!***
     110                 :             : 
     111                 :             : !!****t* m_nctk/nctkarr_t
     112                 :             : !! NAME
     113                 :             : !! nctkarr_t
     114                 :             : !!
     115                 :             : !! FUNCTION
     116                 :             : !!  Stores the name and the shape of a netcdf array
     117                 :             : !!
     118                 :             : !! SOURCE
     119                 :             : 
     120                 :             :  type,public :: nctkarr_t
     121                 :             :    character(len=nctk_slen) :: name        ! name of the array.
     122                 :             :    character(len=4) :: dtype               ! string specifying the type.
     123                 :             :    character(len=nctk_slen) :: shape_str   ! string with the shape. e.g. "dim1, dim2" for [dim1, dim2] array.
     124                 :             :  end type nctkarr_t
     125                 :             : !!***
     126                 :             : 
     127                 :             : !!****s* m_nctk/nctkvar_t
     128                 :             : !! NAME
     129                 :             : !!  nctkvar_t
     130                 :             : !!
     131                 :             : !! FUNCTION
     132                 :             : !!  This structure stores variable information, such as
     133                 :             : !!  name, NetCDF id, type, shape and dimensions. It contains the following elements:
     134                 :             : !!
     135                 :             : !! SOURCE
     136                 :             : 
     137                 :             :  type nctkvar_t
     138                 :             : 
     139                 :             :    integer :: id
     140                 :             :    ! the id used by NetCDF to access this variable.
     141                 :             : 
     142                 :             :    integer :: xtype
     143                 :             :    ! the type of the variable
     144                 :             : 
     145                 :             :    integer :: ndims
     146                 :             :    ! the number of dimensions (0 for scalar variable).
     147                 :             : 
     148                 :             :    integer :: natts
     149                 :             :    ! The number of attributes associated to the variable
     150                 :             : 
     151                 :             :    character(len=nctk_slen) :: name
     152                 :             :    ! the variable name.
     153                 :             : 
     154                 :             :    character(len=nctk_slen) :: dimnames(nctk_max_dims)
     155                 :             :    ! the name corresponding to each dimension
     156                 :             :    ! Only if array variable, only (1:ndims) are relevent
     157                 :             : 
     158                 :             :    integer :: dimids(nctk_max_dims) = -1
     159                 :             :    ! The id of the dimensions. only (1:ndims) are relevent
     160                 :             : 
     161                 :             :    integer :: dimlens(nctk_max_dims) = 0
     162                 :             :    ! the size for each dimension if array variable, only (1:ndims) are relevent
     163                 :             : 
     164                 :             :    !character(len=nctk_slen) :: dimnames(nctk_max_dims)
     165                 :             :    !character(len=nctk_slen), pointer :: ncattnames(:)
     166                 :             :    ! * ncattnames: the name corresponding to all associated attributes
     167                 :             : 
     168                 :             :  end type nctkvar_t
     169                 :             :  !!***
     170                 :             : 
     171                 :             :  public :: nctk_use_classic_for_seq ! Use netcdf-classic for files that are used in sequential.
     172                 :             :                                     ! instead of the default that is netcdf4/hdf5.
     173                 :             :  public :: nctk_idname              ! Return the nc identifier from the name of the variable.
     174                 :             :  public :: nctk_idgroup             ! Return the nc identifier from the name of a group.
     175                 :             :  public :: nctk_ncify               ! Append ".nc" to ipath if ipath does not end with ".nc"
     176                 :             :  public :: nctk_string_from_occopt  ! Return human-readable string with the smearing scheme.
     177                 :             :  public :: nctk_fort_or_ncfile      ! Test wheter a path exists (fortran or nc file) and
     178                 :             :                                     ! select iomode depending on file extension.
     179                 :             :  public :: nctk_try_fort_or_ncfile  ! Return fortran or netcdf filename depending on the existence of the file.
     180                 :             :  public :: nctk_test_mpiio          ! Test at run-time whether the netcdf library supports parallel IO.
     181                 :             : 
     182                 :             :  public :: ab_define_var            ! Helper function used to declare a netcdf variable.
     183                 :             : 
     184                 :             :  ! Helper functions
     185                 :             :  public :: nctk_open_read           ! Open a file in read-only mode.
     186                 :             :  public :: nctk_open_create         ! Create a netcdf file for modifications.
     187                 :             :  public :: nctk_open_modify         ! Open an already existent file for modifications.
     188                 :             :  public :: nctk_add_etsf_header     ! Add the ETSF-IO header.
     189                 :             :  public :: nctk_set_defmode         ! Set the file in define mode (metadata)
     190                 :             :  public :: nctk_set_datamode        ! Set the file in datamode (IO)
     191                 :             :  public :: nctk_set_collective      ! Set collective access for a netcdf variable
     192                 :             : 
     193                 :             :  public :: nctk_def_dims            ! Define dimensions in a netcdf file.
     194                 :             :  interface nctk_def_dims
     195                 :             :    module procedure nctk_def_one_dim
     196                 :             :    module procedure nctk_def_dim_list
     197                 :             :  end interface nctk_def_dims
     198                 :             : 
     199                 :             :  public :: nctk_set_atomic_units    ! Set the value of the attributes "units" and "scale_to_atomic_units".
     200                 :             :  public :: nctk_def_basedims        ! Define the basic dimensions used in ETSF-IO files.
     201                 :             :  public :: nctk_def_scalars_type    ! Declare a list of scalars of the given type.
     202                 :             :  public :: nctk_def_iscalars        ! Declare a list of integer scalars.
     203                 :             :  public :: nctk_def_dpscalars       ! Declare a list of double precision scalars.
     204                 :             :  public :: nctk_write_iscalars      ! Write a list of integer scalars.
     205                 :             :  public :: nctk_write_dpscalars     ! Write a list of double precision scalars.
     206                 :             :  public :: nctk_defnwrite_ivars     ! Declare and write a list of integer scalars.
     207                 :             :  public :: nctk_defnwrite_dpvars    ! Declare and write a list of double precisions scalars.
     208                 :             :  public :: nctk_write_ibz           ! Write k-points in the IBZ and corresponding weights.
     209                 :             : 
     210                 :             :  public :: nctk_def_one_array
     211                 :             :  public :: nctk_def_arrays          ! Define netcdf arrays.
     212                 :             : 
     213                 :             :  interface nctk_def_arrays
     214                 :             :    module procedure nctk_def_one_array
     215                 :             :    module procedure nctk_def_array_list
     216                 :             :  end interface nctk_def_arrays
     217                 :             : 
     218                 :             :  public :: nctk_get_dim
     219                 :             : 
     220                 :             :  public :: nctk_write_datar
     221                 :             :  public :: nctk_read_datar
     222                 :             :  public :: nctk_prepare_mpiio
     223                 :             :  ! This function appears to be required to prevent deadlocks during I/O operations in single mode.
     224                 :             :  ! It's called automatically when using nctk_open_modify and nctk_open_read
     225                 :             : 
     226                 :             :  public :: create_nc_file              ! FIXME: Deprecated
     227                 :             :  public :: write_var_netcdf            ! FIXME: Deprecated
     228                 :             :  public :: write_eig                   ! FIXME: Deprecated
     229                 :             : 
     230                 :             :  !integer,save ABI_PROTECTED, public :: nctk_cache_size = 32000000
     231                 :             :  ! If the cache_size is provided when opening a netCDF-4/HDF5 file, it will be used instead
     232                 :             :  ! of the default (32000000) as the size, in bytes, of the HDF5 chunk cache.
     233                 :             : 
     234                 :             :  !integer,save ABI_PROTECTED, public :: nctk_cache_nelems = 1000
     235                 :             :  ! If cache_nelems is provided when opening a netCDF-4/HDF5 file, it will be used instead
     236                 :             :  ! of the default (1000) as the maximum number of elements in the HDF5 chunk cache.
     237                 :             : 
     238                 :             :  !real,save ABI_PROTECTED, public :: nctk_cache_premtion = 0.75
     239                 :             :  ! If cache_preemption is provided when opening a netCDF-4/HDF5 file, it will be used
     240                 :             :  ! instead of the default (0.75) as the preemption value for the HDF5 chunk cache.
     241                 :             : 
     242                 :             :  logical, save ABI_PROTECTED, public :: nctk_has_mpiio = .false.
     243                 :             :  ! This flag is set to true if the netcdf library supports parallel IO.
     244                 :             :  ! Cannot use CPP flags because nf90_open_par and other similar functions are always
     245                 :             :  ! exported by netcdf. As a consequence we have to check at run-time if we can
     246                 :             :  ! perform parallel IO and we use nctk_has_mpiio to select the IO algorithms.
     247                 :             : 
     248                 :             : CONTAINS
     249                 :             : 
     250                 :             : 
     251                 :             : !!****f* m_nctk/nctk_set_default_for_seq
     252                 :             : !! NAME
     253                 :             : !!  nctk_set_default_for_seq
     254                 :             : !!
     255                 :             : !! FUNCTION
     256                 :             : !!  Use netcdf classic mode for new files when only sequential-IO needs to be performed
     257                 :             : !!
     258                 :             : !! SOURCE
     259                 :             : 
     260                 :           0 : subroutine nctk_use_classic_for_seq()
     261                 :             : 
     262                 :             :  ! Use netcdf classic mode.
     263                 :           0 :  def_cmode_for_seq_create = ior(nf90_clobber, nf90_write)
     264                 :           0 :  ABI_COMMENT("Using netcdf-classic mode")
     265                 :             : 
     266                 :           0 : end subroutine nctk_use_classic_for_seq
     267                 :             : !!***
     268                 :             : 
     269                 :             : !----------------------------------------------------------------------
     270                 :             : 
     271                 :             : !!****f* m_nctk/nctk_idname
     272                 :             : !! NAME
     273                 :             : !!  nctk_idname
     274                 :             : !!
     275                 :             : !! FUNCTION
     276                 :             : !!  Return the nc identifier from the name of the variable
     277                 :             : !!
     278                 :             : !! SOURCE
     279                 :             : 
     280                 :     2967665 : integer function nctk_idname(ncid, varname) result(varid)
     281                 :             : 
     282                 :             : !Arguments ------------------------------------
     283                 :             :  integer,intent(in) :: ncid
     284                 :             :  character(len=*),intent(in) :: varname
     285                 :             : 
     286                 :             : !Local variables-------------------------------
     287                 :             : !scalars
     288                 :             :  integer :: ncerr
     289                 :             :  character(len=1000) :: msg
     290                 :             : ! *********************************************************************
     291                 :             : 
     292                 :     2967665 :  ncerr = nf90_inq_varid(ncid, varname, varid)
     293                 :             : 
     294         [ -  + ]:     2967665 :  if (ncerr /= nf90_noerr) then
     295                 :             :    write(msg,'(6a)')&
     296         [ #  # ]:           0 :      "NetCDF library returned: `",trim(nf90_strerror(ncerr)), "`", ch10,&
     297                 :           0 :      "while trying to get the ncid of variable: ",trim(varname)
     298                 :           0 :    ABI_ERROR(msg)
     299                 :             :  end if
     300                 :             : 
     301                 :     2967665 : end function nctk_idname
     302                 :             : !!***
     303                 :             : 
     304                 :             : !----------------------------------------------------------------------
     305                 :             : 
     306                 :             : !!****f* m_nctk/nctk_idgroup
     307                 :             : !! NAME
     308                 :             : !!  nctk_idgroup
     309                 :             : !!
     310                 :             : !! FUNCTION
     311                 :             : !!  Return the nc identifier from the name of a group
     312                 :             : !!
     313                 :             : !! SOURCE
     314                 :             : 
     315                 :       17110 : integer function nctk_idgroup(ncid, grpname) result(grpid)
     316                 :             : 
     317                 :             : !Arguments ------------------------------------
     318                 :             :  integer,intent(in) :: ncid
     319                 :             :  character(len=*),intent(in) :: grpname
     320                 :             : 
     321                 :             : !Local variables-------------------------------
     322                 :             :  integer :: ncerr
     323                 :             :  character(len=1000) :: msg
     324                 :             : ! *********************************************************************
     325                 :             : 
     326                 :       17110 :  ncerr = nf90_inq_ncid(ncid, grpname, grpid)
     327                 :             : 
     328         [ -  + ]:       17110 :  if (ncerr /= nf90_noerr) then
     329                 :             :    write(msg,'(6a)')&
     330         [ #  # ]:           0 :      "NetCDF library returned: `",trim(nf90_strerror(ncerr)), "`", ch10,&
     331                 :           0 :      "while trying to get the ncid of group: ",trim(grpname)
     332                 :           0 :    ABI_ERROR(msg)
     333                 :             :  end if
     334                 :             : 
     335                 :       17110 : end function nctk_idgroup
     336                 :             : !!***
     337                 :             : 
     338                 :             : !----------------------------------------------------------------------
     339                 :             : !!****f* m_nctk/nctk_ncify
     340                 :             : !! NAME
     341                 :             : !!  nctk_ncify
     342                 :             : !!
     343                 :             : !! FUNCTION
     344                 :             : !!  Append ".nc" to ipath if ipath does not end with ".nc"
     345                 :             : !!
     346                 :             : !! SOURCE
     347                 :             : 
     348                 :       56913 : function nctk_ncify(ipath) result(opath)
     349                 :             : 
     350                 :             :  character(len=*),intent(in) :: ipath
     351                 :             :  character(len=fnlen) :: opath
     352                 :             : ! *********************************************************************
     353                 :             : 
     354                 :       56913 :  if (.not. endswith(ipath, ".nc")) then
     355         [ +  + ]:       54616 :    opath = trim(ipath)//'.nc'
     356                 :             :  else
     357         [ -  + ]:        2297 :    opath = ipath
     358                 :             :  end if
     359                 :             : 
     360         [ +  + ]:       56913 : end function nctk_ncify
     361                 :             : !!***
     362                 :             : 
     363                 :             : 
     364                 :             : !----------------------------------------------------------------------
     365                 :             : 
     366                 :             : !!****f* m_nctk/nctk_string_from_occopt
     367                 :             : !! NAME
     368                 :             : !!  nctk_string_from_occopt
     369                 :             : !!
     370                 :             : !! FUNCTION
     371                 :             : !!
     372                 :             : !! SOURCE
     373                 :             : 
     374                 :       27726 : pure function nctk_string_from_occopt(occopt) result(smearing)
     375                 :             : 
     376                 :             :  integer,intent(in) :: occopt
     377                 :             :  character(len=etsfio_charlen) :: smearing
     378                 :             : ! *********************************************************************
     379                 :             : 
     380                 :       29217 :  select case (occopt)
     381                 :             :  case (3)
     382                 :        1491 :    smearing = "Fermi-Dirac"
     383                 :             :  case (4)
     384                 :        1802 :    smearing = "cold smearing of N. Marzari with minimization of the bump"
     385                 :             :  case (5)
     386                 :          42 :    smearing = "cold smearing of N. Marzari with monotonic function in the tail"
     387                 :             :  case (6)
     388                 :          30 :    smearing = "Methfessel and Paxton"
     389                 :             :  case (7)
     390                 :        3573 :    smearing = "gaussian"
     391                 :             :  case (8)
     392                 :           0 :    smearing = "uniform"
     393                 :             :  case default
     394   [ +  +  +  +  :       27726 :    smearing = "none"
                +  -  + ]
     395                 :             :  end select
     396                 :             : 
     397                 :       27726 : end function nctk_string_from_occopt
     398                 :             : !!***
     399                 :             : 
     400                 :             : !----------------------------------------------------------------------
     401                 :             : 
     402                 :             : !!****f* m_nctk/nctk_fort_or_ncfile
     403                 :             : !! NAME
     404                 :             : !!  nctk_fort_or_ncfile
     405                 :             : !!
     406                 :             : !! FUNCTION
     407                 :             : !!  Return the iomode used to perform IO operations on filename.
     408                 :             : !!  If filename does not exist, a similar file with extension `.nc` is tried
     409                 :             : !!  and iomode is set to IO_MODE_ETSF if the file exists.
     410                 :             : !!  This trick is used to run the Abinit test suite in netcdf mode without changing the input files.
     411                 :             : !!  The modification (if any) is logged to std_out.
     412                 :             : !!
     413                 :             : !! SIDE EFFECTS
     414                 :             : !!  filename=Tentative filename in input. Changed to netcdf file if input filename does not exist
     415                 :             : !!   and a file with netcdf extension is found.
     416                 :             : !!
     417                 :             : !! OUTPUT
     418                 :             : !!  iomode=Flag selecting the IO library. Set to IO_MODE_ETSF if netcdf file, else IO_MODE_MPI
     419                 :             : !!    if MPI supports it, finally IO_MODE_FORTRAN
     420                 :             : !!  errmsg=String with error message. Use `if (len_trim(errmsg) /= 0) ABI_ERROR(errmsg)`
     421                 :             : !!    to handle possible errors in the caller.
     422                 :             : !!
     423                 :             : !! SOURCE
     424                 :             : 
     425                 :          65 : subroutine nctk_fort_or_ncfile(filename, iomode, errmsg)
     426                 :             : 
     427                 :             :  character(len=*),intent(inout) :: filename
     428                 :             :  character(len=*),intent(out) :: errmsg
     429                 :             :  integer,intent(out) :: iomode
     430                 :             : ! *********************************************************************
     431                 :          65 :   errmsg = ""
     432                 :             : 
     433                 :             :  ! Default value
     434                 :             : #ifdef HAVE_MPI_IO
     435                 :          65 :  iomode = IO_MODE_MPI
     436                 :             : #else
     437                 :             :  iomode = IO_MODE_FORTRAN
     438                 :             : #endif
     439                 :             : 
     440                 :             :  !  Checking the existence of data file
     441         [ +  + ]:          65 :  if (.not.file_exists(filename)) then
     442                 :             :    ! Trick needed to run Abinit test suite in netcdf mode.
     443         [ +  - ]:          50 :    if (file_exists(nctk_ncify(filename))) then
     444                 :          50 :      write(std_out,"(3a)")"- File: ",trim(filename)," does not exist but found netcdf file with similar name."
     445   [ +  -  -  + ]:         100 :      filename = nctk_ncify(filename); iomode = IO_MODE_ETSF
     446                 :             :    end if
     447         [ -  + ]:          50 :    if (.not. file_exists(filename)) then
     448   [ #  #  #  # ]:           0 :      errmsg = 'Missing file: '//trim(filename)
     449                 :             :    end if
     450                 :             :  end if
     451                 :             : 
     452         [ +  - ]:          65 : end subroutine nctk_fort_or_ncfile
     453                 :             : !!***
     454                 :             : 
     455                 :             : !----------------------------------------------------------------------
     456                 :             : 
     457                 :             : !!****f* m_nctk/nctk_try_fort_or_ncfile
     458                 :             : !! NAME
     459                 :             : !!  nctk_try_fort_or_ncfile
     460                 :             : !!
     461                 :             : !! FUNCTION
     462                 :             : !!  If filename does not exist, a similar file with extension `.nc` is tried
     463                 :             : !!  This trick is used to run the Abinit test suite in netcdf mode without changing the input files.
     464                 :             : !!  The modification (if any) is logged to unit (Default: std_out)
     465                 :             : !!
     466                 :             : !! SIDE EFFECTS
     467                 :             : !!  filename=Tentative filename in input. Changed to netcdf file if input filename does not exist
     468                 :             : !!   and a file with netcdf extension is found.
     469                 :             : !!
     470                 :             : !! OUTPUT
     471                 :             : !!  errmsg=String with error message if return value /= 0
     472                 :             : !!
     473                 :             : !! SOURCE
     474                 :             : 
     475                 :       11839 : integer function nctk_try_fort_or_ncfile(filename, errmsg, unit) result(ierr)
     476                 :             : 
     477                 :             : !Arguments ------------------------------------
     478                 :             :  character(len=*),intent(inout) :: filename
     479                 :             :  character(len=*),intent(out) :: errmsg
     480                 :             :  integer,optional,intent(in) :: unit
     481                 :             : 
     482                 :             : !Local variables-------------------------------
     483                 :             :  integer :: unt
     484                 :             : ! *********************************************************************
     485                 :             : 
     486                 :           0 :  unt = std_out; if (present(unit)) unt = unit
     487         [ +  - ]:       11839 :  ierr = 0; errmsg = ""
     488                 :             : 
     489         [ +  + ]:       11839 :  if (.not.file_exists(filename)) then
     490                 :             :    ! Try netcdf exists.
     491         [ +  - ]:        2510 :    if (file_exists(nctk_ncify(filename))) then
     492         [ +  - ]:        2510 :      if (unt /= dev_null) then
     493                 :        2510 :        write(unt,"(3a)")"- File: ",trim(filename)," does not exist but found netcdf file with similar name."
     494                 :             :      end if
     495   [ +  -  -  + ]:        5020 :      filename = nctk_ncify(filename)
     496                 :             :    end if
     497         [ +  - ]:        2510 :    if (.not. file_exists(filename)) then
     498   [ #  #  #  # ]:           0 :      ierr = 1; errmsg = 'Cannot find file: '//trim(filename)
     499                 :             :    end if
     500                 :             :  end if
     501                 :             : 
     502         [ -  + ]:       11839 : end function nctk_try_fort_or_ncfile
     503                 :             : !!***
     504                 :             : 
     505                 :             : !----------------------------------------------------------------------
     506                 :             : 
     507                 :             : !!****f* m_nctk/nctk_test_mpiio
     508                 :             : !! NAME
     509                 :             : !!  nctk_test_mpiio
     510                 :             : !!
     511                 :             : !! FUNCTION
     512                 :             : !!  Test at run-time whether the netcdf library supports parallel IO and
     513                 :             : !!  set the value of the module variable `nctk_has_mpiio`.
     514                 :             : !!  This is a COLLECTIVE routine that should be called by all processors
     515                 :             : !!  in MPI_COMM_WORLD at the beginning of the calculation
     516                 :             : !!
     517                 :             : !! INPUTS
     518                 :             : !!  [print_warning]=TRUE if a warning about paral_kgb use has to be printed
     519                 :             : !!                  Optional, default=yes
     520                 :             : !!
     521                 :             : !! SOURCE
     522                 :             : 
     523                 :        1451 : subroutine nctk_test_mpiio(print_warning)
     524                 :             : 
     525                 :             :  logical,intent(in),optional :: print_warning
     526                 :             : 
     527                 :             : !Local variables-------------------------------
     528                 :             : !scalars
     529                 :             :  logical :: my_print_warning
     530                 :             : #ifdef HAVE_NETCDF_MPI
     531                 :             :  integer,parameter :: master=0
     532                 :             :  integer :: ierr,ncid,ncerr
     533                 :             :  character(len=500) :: msg
     534                 :             :  character(len=fnlen) :: apath
     535                 :             : #endif
     536                 :             : ! *********************************************************************
     537                 :             : 
     538                 :        1451 :  nctk_has_mpiio = .False.
     539         [ +  + ]:        1451 :  my_print_warning=.true. ; if (present(print_warning)) my_print_warning=print_warning
     540                 :             : 
     541                 :             : !FIXME nf90create fails when using NVHPC
     542                 :             : ! This might be due to my environment, maybe not, need to investigate this...
     543                 :             : !!#ifndef FC_NVHPC
     544                 :             : #ifdef HAVE_NETCDF_MPI
     545         [ +  + ]:        1451 :  if (xmpi_comm_rank(xmpi_world) == master) then
     546                 :             :    ! Try to open a file with hdf5.
     547                 :        1170 :    apath = pick_aname()
     548                 :             :    ncerr = nf90_create(apath, cmode=ior(ior(nf90_netcdf4, nf90_mpiio), nf90_write), ncid=ncid, &
     549                 :        1170 :      comm=xmpi_comm_self, info=xmpio_info)
     550                 :             : 
     551         [ +  - ]:        1170 :    if (ncerr == nf90_noerr) then
     552                 :        1170 :      nctk_has_mpiio = .True.
     553                 :        1170 :      call wrtout(std_out," Netcdf library supports MPI-IO", "COLL")
     554         [ #  # ]:           0 :    else if (ncerr == nf90_enopar) then
     555                 :             :      ! This is the value returned by the C function ifndef USE_PARALLEL
     556                 :           0 :      ABI_WARNING(sjoin("Netcdf lib does not support MPI-IO and: ", nf90_strerror(ncerr)))
     557                 :           0 :      nctk_has_mpiio = .False.
     558                 :             :    else
     559                 :             :      ! Maybe something wrong in the low-level layer!
     560                 :           0 :      ABI_WARNING(sjoin("Strange, netcdf seems to support MPI-IO but: ", nf90_strerror(ncerr)))
     561                 :           0 :      nctk_has_mpiio = .False.
     562                 :             :    end if
     563                 :             : 
     564                 :        1170 :    ncerr = nf90_close(ncid)
     565                 :        1170 :    call delete_file(apath, ierr)
     566                 :             :  end if
     567                 :             : 
     568                 :             :  ! Master broadcast nctk_has_mpiio
     569                 :        1451 :  call xmpi_bcast(nctk_has_mpiio,master,xmpi_world,ierr)
     570                 :             : 
     571   [ -  +  -  - ]:        1451 :  if ((.not. nctk_has_mpiio) .and. my_print_warning) then
     572                 :             :    write(msg,"(5a)") &
     573                 :           0 :       "The netcdf library does not support parallel IO, see message above",ch10,&
     574                 :           0 :       "Abinit won't be able to produce files in parallel when e.g. paral_kgb == 1 is used.",ch10,&
     575                 :           0 :       "Action: install a netcdf4+HDF5 library with MPI-IO support."
     576                 :           0 :    ABI_WARNING(msg)
     577                 :             :  end if
     578                 :             : #endif
     579                 :             : !!#endif
     580                 :             : 
     581                 :             : #ifdef HAVE_NETCDF_DEFAULT
     582         [ -  + ]:        1451 :  if (.not. nctk_has_mpiio) then
     583                 :           0 :    ABI_ERROR("--netcdf-default is on but netcdf library does not support MPI-IO. Aborting now")
     584                 :             :  end if
     585                 :             : #endif
     586                 :             : 
     587                 :        1451 : end subroutine nctk_test_mpiio
     588                 :             : !!***
     589                 :             : 
     590                 :             : !!****f* m_nctk/str2xtype
     591                 :             : !! NAME
     592                 :             : !!  str2xtype
     593                 :             : !!
     594                 :             : !! FUNCTION
     595                 :             : !!  Return the netcdf type from a string. Possible values:
     596                 :             : !!    c or ch   for NF90_CHAR
     597                 :             : !!    i or int  for NF90_INTtrue
     598                 :             : !!   sp         for NF90_FLOAT
     599                 :             : !!   dp         for NF90_DOUBLE
     600                 :             : !!
     601                 :             : !! SOURCE
     602                 :             : 
     603                 :     1201761 : integer function str2xtype(string) result(xtype)
     604                 :             : 
     605                 :             : !Arguments ------------------------------------
     606                 :             :  character(len=*),intent(in) :: string
     607                 :             : ! *********************************************************************
     608                 :             : 
     609                 :             :  !Type  FORTRAN API Mnemonic    Bits
     610                 :             :  !byte      NF90_BYTE           8
     611                 :             :  !char      NF90_CHAR           8
     612                 :             :  !short     NF90_SHORT          16
     613                 :             :  !int       NF90_INT            32
     614                 :             :  !float     NF90_FLOAT          32
     615                 :             :  !double    NF90_DOUBLE         64
     616                 :             : 
     617                 :             :  select case (string)
     618                 :             :  case ("c", "ch", "char")
     619                 :             :    xtype = NF90_CHAR
     620                 :             :  case ("i", "int")
     621                 :             :    xtype = NF90_INT
     622                 :             :  case ("sp")
     623                 :             :    xtype = NF90_FLOAT
     624                 :             :  case ("dp")
     625                 :           0 :    xtype = NF90_DOUBLE
     626                 :             :  case default
     627         [ +  - ]:     1201761 :    ABI_ERROR(sjoin("Invalid string type:", string))
     628                 :             :  end select
     629                 :             : 
     630                 :     1201761 : end function str2xtype
     631                 :             : !!***
     632                 :             : 
     633                 :             : !!****f* m_nctk/bail_if_ncerr
     634                 :             : !! NAME
     635                 :             : !!  bail_if_ncerr
     636                 :             : !!
     637                 :             : !! FUNCTION
     638                 :             : !!
     639                 :             : !! INPUTS
     640                 :             : !!  ncerr=Netcdf error
     641                 :             : !!  line=line number of the file where problem occurred
     642                 :             : !!  file=name of the f90 file containing the caller
     643                 :             : !!
     644                 :             : !! SOURCE
     645                 :             : 
     646                 :             : logical function bail_if_ncerr(ncerr, file, line) result(bail)
     647                 :             : 
     648                 :             : !Arguments ------------------------------------
     649                 :             :  integer,intent(in) :: ncerr
     650                 :             :  character(len=*),optional,intent(in) :: file
     651                 :             :  integer,optional,intent(in) :: line
     652                 :             : ! *********************************************************************
     653                 :             : 
     654                 :             :  bail = (ncerr /= nf90_noerr)
     655                 :             : 
     656                 :             :  if (bail) then
     657                 :             :    einfo%ncerr = ncerr
     658                 :             :    einfo%file = "Subroutine Unknown"; if (present(file)) einfo%file = file
     659                 :             :    einfo%line = 0; if (present(line)) einfo%line = line
     660                 :             :    ! Append Netcdf string to user-defined message.
     661                 :             :    write(einfo%msg,'(2a)')'NetCDF library raised: ',trim(nf90_strerror(ncerr))
     662                 :             :  end if
     663                 :             : 
     664                 :             : end function bail_if_ncerr
     665                 :             : !!***
     666                 :             : 
     667                 :             : !----------------------------------------------------------------------
     668                 :             : 
     669                 :             : !!****f* m_nctk/nctk_open_read
     670                 :             : !! NAME
     671                 :             : !!  nctk_open_read
     672                 :             : !!
     673                 :             : !! FUNCTION
     674                 :             : !!   Open a netcdf file in read-only mode. Return exit status.
     675                 :             : !!
     676                 :             : !! INPUTS
     677                 :             : !!  ncid=Netcdf identifier.
     678                 :             : !!  comm=MPI communicator.
     679                 :             : !!
     680                 :             : !! SOURCE
     681                 :             : 
     682                 :       22079 : integer function nctk_open_read(ncid, path, comm) result(ncerr)
     683                 :             : 
     684                 :             : !Arguments ------------------------------------
     685                 :             :  integer,intent(out) :: ncid
     686                 :             :  integer,intent(in) :: comm
     687                 :             :  character(len=*),intent(in) :: path
     688                 :             : 
     689                 :             : !Local variables-------------------------------
     690                 :             :  integer :: nprocs
     691                 :             : ! *********************************************************************
     692                 :             : 
     693                 :       22079 :  nprocs = xmpi_comm_size(comm)
     694                 :             : 
     695                 :             :  ! Enforce netcdf4 only if the communicator contains more than one processor.
     696   [ +  +  +  + ]:       22079 :  if (nctk_has_mpiio .and. nprocs > 1) then
     697                 :             : #ifdef HAVE_NETCDF_MPI
     698                 :             :    ncerr = nf90_open(path, mode=ior(ior(nf90_netcdf4, nf90_mpiio), nf90_nowrite),&
     699                 :          48 :                      comm=comm, info=xmpio_info, ncid=ncid)
     700                 :             : #else
     701                 :             :    ncerr = nf90_einval
     702                 :             :    ABI_WARNING("Netcdf without MPI support. Cannot open file, will abort in caller")
     703                 :             : #endif
     704         [ -  + ]:          48 :    NCF_CHECK_MSG(ncerr, sjoin("opening file:", path))
     705                 :             :  else
     706                 :       22031 :    ncerr = nf90_open(path, mode=nf90_nowrite, ncid=ncid)
     707         [ -  + ]:       22031 :    NCF_CHECK_MSG(ncerr, sjoin("Opening file:", path))
     708                 :             :    !if (ncerr /= NC_EHDFERR) then
     709                 :             :    !  ncerr = nf90_open(path, mode=ior(ior(nf90_netcdf4), nf90_nowrite), comm=comm, info=xmpio_info, ncid=ncid)
     710                 :             :    !end if
     711         [ -  + ]:       22031 :    if (nprocs > 1) then
     712                 :           0 :      ncerr = nf90_einval
     713                 :           0 :      ABI_WARNING("netcdf without MPI-IO support with nprocs > 1! Will abort in the caller")
     714                 :             :    end if
     715                 :             :  end if
     716                 :             : 
     717                 :       22079 : end function nctk_open_read
     718                 :             : !!***
     719                 :             : 
     720                 :             : !----------------------------------------------------------------------
     721                 :             : 
     722                 :             : !!****f* m_nctk/nctk_open_create
     723                 :             : !! NAME
     724                 :             : !!  nctk_open_create
     725                 :             : !!
     726                 :             : !! FUNCTION
     727                 :             : !!  Create and open the netcdf file. Return exis status.
     728                 :             : !!
     729                 :             : !! INPUTS
     730                 :             : !!  path=Name of the file
     731                 :             : !!  comm=MPI communicator.
     732                 :             : !!
     733                 :             : !! OUTPUT
     734                 :             : !!  ncid=Netcdf identifier.
     735                 :             : !!
     736                 :             : !! SOURCE
     737                 :             : 
     738                 :       15894 : integer function nctk_open_create(ncid, path, comm) result(ncerr)
     739                 :             : 
     740                 :             : !Arguments ------------------------------------
     741                 :             :  integer,intent(out) :: ncid
     742                 :             :  integer,intent(in) :: comm
     743                 :             :  character(len=*),intent(in) :: path
     744                 :             : 
     745                 :             : !Local variables-------------------------------
     746                 :             :  integer :: input_len, cmode
     747                 :             :  character(len=strlen) :: my_string
     748                 :             : ! *********************************************************************
     749                 :             : 
     750                 :             :  ! Always use mpiio mode (i.e. hdf5) if available so that one can perform parallel IO
     751         [ +  + ]:       15894 :  if (nctk_has_mpiio) then
     752                 :       15658 :    ncerr = nf90_einval
     753                 :             : #ifdef HAVE_NETCDF_MPI
     754                 :       15658 :    write(my_string,'(2a)') "- Creating HDf5 file with MPI-IO support: ",trim(path)
     755                 :       15658 :    call wrtout(std_out, my_string)
     756                 :             :    ! Believe it or not, I have to use xmpi_comm_self even in sequential to avoid weird SIGSEV in the MPI layer!
     757                 :       15658 :    ncerr = nf90_create(path, cmode=ior(ior(nf90_netcdf4, nf90_mpiio), nf90_write), ncid=ncid, comm=comm, info=xmpio_info)
     758                 :             : #endif
     759                 :             :  else
     760                 :             :    ! Note that here we don't enforce nf90_netcdf4 hence the netcdf file with be in classic model.
     761                 :         236 :    write(my_string,'(2a)') "- Creating HDf5 file WITHOUT MPI-IO support: ",trim(path)
     762                 :         236 :    call wrtout(std_out, my_string)
     763                 :             :    !ncerr = nf90_create(path, ior(nf90_clobber, nf90_write), ncid)
     764                 :         236 :    cmode = def_cmode_for_seq_create
     765                 :         236 :    ncerr = nf90_create(path, cmode=cmode, ncid=ncid)
     766         [ -  + ]:         236 :    if (xmpi_comm_size(comm) > 1) then
     767                 :           0 :      ABI_WARNING("netcdf without MPI-IO support with nprocs > 1!")
     768                 :             :    end if
     769                 :             :  end if
     770         [ -  + ]:       15894 :  NCF_CHECK(ncerr)
     771                 :             : 
     772                 :             :  ! Write etsf_header: file format, version and conventions.
     773         [ -  + ]:       15894 :  NCF_CHECK(nf90_put_att(ncid, NF90_GLOBAL, "file_format", etsfio_file_format))
     774         [ -  + ]:       15894 :  NCF_CHECK(nf90_put_att(ncid, NF90_GLOBAL, "file_format_version", etsfio_version))
     775         [ -  + ]:       15894 :  NCF_CHECK(nf90_put_att(ncid, NF90_GLOBAL, "Conventions", etsfio_conventions))
     776                 :             : 
     777                 :             :  ! Add info on the code that produced this file. These are extensions not in the standard.
     778         [ -  + ]:       15894 :  NCF_CHECK(nf90_put_att(ncid, NF90_GLOBAL, "code", "Abinit"))
     779         [ -  + ]:       15894 :  NCF_CHECK(nf90_put_att(ncid, NF90_GLOBAL, "abinit_version", abinit_version))
     780                 :             : 
     781                 :             :  ! Define the basic dimensions used in ETSF-IO files.
     782         [ -  + ]:       15894 :  NCF_CHECK(nctk_def_basedims(ncid, defmode=.True.))
     783                 :             : 
     784                 :             :  ! INPUT_STRING is allocated and initialized in parsefile
     785         [ +  + ]:       15894 :  if (allocated(INPUT_STRING)) then
     786                 :             :    ! Write string with input.
     787         [ +  + ]:       15817 :    my_string = trim(INPUT_STRING)
     788   [ +  +  +  + ]:       15817 :    if (DTSET_IDX /= -1 .and. index(INPUT_STRING, "jdtset ") == 0) then
     789   [ +  -  +  + ]:       14030 :      my_string = "jdtset " // trim(itoa(DTSET_IDX)) // "  " // trim(INPUT_STRING)
     790                 :             :    end if
     791                 :             : 
     792                 :       15817 :    input_len = len_trim(my_string)
     793         [ -  + ]:       15817 :    NCF_CHECK(nctk_def_dims(ncid, nctkdim_t("input_len", input_len)))
     794         [ -  + ]:       15817 :    NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("input_string", "c", "input_len")))
     795                 :             :    !print *, "input_len, strlen:", input_len, strlen
     796                 :             : 
     797         [ +  - ]:       15817 :    if (xmpi_comm_rank(comm) == 0) then
     798         [ -  + ]:       15817 :      NCF_CHECK(nctk_set_datamode(ncid))
     799                 :             :      ! Pass my_string(1:input_len)) instead from trim(string) to avoid SIGSEV on higgs_intel_19.0_serial
     800         [ -  + ]:       15817 :      NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "input_string"), my_string(1:input_len)))
     801         [ -  + ]:       15817 :      NCF_CHECK(nctk_set_defmode(ncid))
     802                 :             :    end if
     803                 :             :  end if
     804                 :             : 
     805                 :       15894 : end function nctk_open_create
     806                 :             : !!***
     807                 :             : 
     808                 :             : !----------------------------------------------------------------------
     809                 :             : 
     810                 :             : !!****f* m_nctk/nctk_open_modify
     811                 :             : !! NAME
     812                 :             : !!  nctk_open_modfy
     813                 :             : !!
     814                 :             : !! FUNCTION
     815                 :             : !!   Open an already existent netcdf file for modifications. Return exit status.
     816                 :             : !!
     817                 :             : !! INPUTS
     818                 :             : !!  path=File name.
     819                 :             : !!  comm=MPI communicator.
     820                 :             : !!
     821                 :             : !! OUTPUT
     822                 :             : !!  ncid=Netcdf identifier.
     823                 :             : !!
     824                 :             : !! SOURCE
     825                 :             : 
     826                 :       11869 : integer function nctk_open_modify(ncid, path, comm) result(ncerr)
     827                 :             : 
     828                 :             : !Arguments ------------------------------------
     829                 :             :  integer,intent(out) :: ncid
     830                 :             :  character(len=*),intent(in) :: path
     831                 :             :  integer,intent(in) :: comm
     832                 :             : ! *********************************************************************
     833                 :             : 
     834   [ +  +  -  + ]:       11869 :  if (.not. nctk_has_mpiio .and. xmpi_comm_size(comm) > 1) then
     835                 :           0 :    ABI_ERROR("netcdf without MPI-IO support and nprocs > 1!")
     836                 :             :  end if
     837                 :             : 
     838   [ +  +  +  + ]:       11869 :  if (xmpi_comm_size(comm) > 1 .or. nctk_has_mpiio) then
     839                 :       11868 :    call wrtout(std_out, sjoin(" nctk_open_modify: Opening HDf5 file with MPI-IO support:", path))
     840                 :             : #ifdef HAVE_NETCDF_MPI
     841                 :             :    ncerr = nf90_open_par(path, cmode=ior(ior(nf90_netcdf4, nf90_mpiio), nf90_write), &
     842                 :       11868 :                          comm=comm, info=xmpio_info, ncid=ncid)
     843         [ -  + ]:       11868 :    NCF_CHECK_MSG(ncerr, sjoin("nf90_open_par: ", path))
     844                 :             : #else
     845                 :             :    ABI_ERROR("nprocs > 1 but netcdf does not support MPI-IO")
     846                 :             : #endif
     847                 :             :  else
     848                 :           1 :    call wrtout(std_out, sjoin(" nctk_open_modify: Opening netcdf file without MPI-IO support:", path))
     849                 :           1 :    ncerr = nf90_open(path, nf90_write, ncid)
     850         [ -  + ]:           1 :    NCF_CHECK_MSG(ncerr, sjoin("nf90_open: ", path))
     851                 :             :  end if
     852                 :             : 
     853                 :             :  ! Set file in define mode.
     854         [ -  + ]:       11869 :  NCF_CHECK(nctk_set_defmode(ncid))
     855                 :             :  !call wrtout(std_out, "- Returning from nctk_open_modify")
     856                 :             : 
     857                 :       11869 : end function nctk_open_modify
     858                 :             : !!***
     859                 :             : 
     860                 :             : !----------------------------------------------------------------------
     861                 :             : 
     862                 :             : !!****f* m_nctk/nctk_add_etsf_header
     863                 :             : !! NAME
     864                 :             : !!  nctk_add_etsf_header
     865                 :             : !!
     866                 :             : !! FUNCTION
     867                 :             : !!   Add the etsf-io header to a file associated to a netcdf file handler.
     868                 :             : !!
     869                 :             : !! INPUTS
     870                 :             : !!  ncid=Netcdf file identifier.
     871                 :             : !!  * version = the number of version to be created.
     872                 :             : !!  * title = (optional) a title for the file (80 characters max).
     873                 :             : !!  * history = (optional) the first line of history (1024 characters max).
     874                 :             : !!  * with_etsf_header = (optional) if true, will create a header
     875                 :             : !!                       as defined in the ETSF specifications (default is .true.).
     876                 :             : !!                       When value is .false., arguments title, history and version
     877                 :             : !!                       are ignored.
     878                 :             : !!
     879                 :             : !! SOURCE
     880                 :             : 
     881                 :        4574 : integer function nctk_add_etsf_header(ncid, title, history) result(ncerr)
     882                 :             : 
     883                 :             : !Arguments ------------------------------------
     884                 :             :  integer,intent(in) :: ncid
     885                 :             :  character(len=*),optional,intent(in) :: title,history
     886                 :             : 
     887                 :             : !Local variables-------------------------------
     888                 :             :  !integer :: ncerr
     889                 :             :  character(len=*), parameter :: file_format = "ETSF Nanoquanta"
     890                 :             :  character(len=*), parameter :: conventions = "http://www.etsf.eu/fileformats/"
     891                 :             :  real :: format_version = 3.3 ! Real is not a good choice for a version!
     892                 :             : ! *********************************************************************
     893                 :             : 
     894                 :        4574 :  ncerr = nctk_set_defmode(ncid)
     895         [ +  - ]:        4574 :  if (ncerr /= nf90_noerr) return
     896                 :             : 
     897                 :             :  ! The file format
     898                 :        4574 :  ncerr = nf90_put_att(ncid, NF90_GLOBAL, "file_format", file_format)
     899         [ +  - ]:        4574 :  if (ncerr /= nf90_noerr) return
     900                 :             : 
     901                 :             :  ! The version
     902                 :        4574 :  ncerr = nf90_put_att(ncid, NF90_GLOBAL, "file_format_version", format_version)
     903         [ +  - ]:        4574 :  if (ncerr /= nf90_noerr) return
     904                 :             : 
     905                 :             :  ! The conventions
     906                 :        4574 :  ncerr = nf90_put_att(ncid, NF90_GLOBAL, "Conventions", conventions)
     907         [ +  - ]:        4574 :  if (ncerr /= nf90_noerr) return
     908                 :             : 
     909                 :             :  ! The history if present
     910         [ +  - ]:        4574 :  if (present(history)) then
     911                 :        4574 :    ncerr = nf90_put_att(ncid, NF90_GLOBAL, "history", history(1:min(1024, len(history))))
     912         [ +  - ]:        4574 :    if (ncerr /= nf90_noerr) return
     913                 :             :  end if
     914                 :             : 
     915                 :             :  ! The title if present
     916         [ +  - ]:        4574 :  if (present(title)) then
     917                 :        4574 :    ncerr = nf90_put_att(ncid, NF90_GLOBAL, "title", title(1:min(80, len(title))))
     918         [ +  - ]:        4574 :    if (ncerr /= nf90_noerr) return
     919                 :             :  end if
     920                 :             : 
     921                 :             :  ! These are extensions not in the standard.
     922                 :             :  ! Add info on the code that produced this file
     923                 :        4574 :  ncerr = nf90_put_att(ncid, NF90_GLOBAL, "code", "Abinit")
     924         [ +  - ]:        4574 :  if (ncerr /= nf90_noerr) return
     925                 :             : 
     926                 :        4574 :  ncerr = nf90_put_att(ncid, NF90_GLOBAL, "code_version", ABINIT_VERSION)
     927                 :             :  if (ncerr /= nf90_noerr) return
     928                 :             : 
     929                 :             : end function nctk_add_etsf_header
     930                 :             : !!***
     931                 :             : 
     932                 :             : !----------------------------------------------------------------------
     933                 :             : 
     934                 :             : !!****f* m_nctk/nctk_set_defmode
     935                 :             : !! NAME
     936                 :             : !!  nctk_set_defmode
     937                 :             : !!
     938                 :             : !! FUNCTION
     939                 :             : !!   Set the file in define mode, return exit status.
     940                 :             : !!
     941                 :             : !! INPUTS
     942                 :             : !!  ncid=Netcdf identifier.
     943                 :             : !!
     944                 :             : !! SOURCE
     945                 :             : 
     946                 :      214898 : integer function nctk_set_defmode(ncid) result(ncerr)
     947                 :             : 
     948                 :             : !Arguments ------------------------------------
     949                 :             :  integer,intent(in) :: ncid
     950                 :             : ! *********************************************************************
     951                 :             : 
     952                 :      214898 :  ncerr = nf90_redef(ncid)
     953                 :             :  ! Use same trick as in etsf_io
     954         [ -  + ]:      214898 :  if (ncerr /= nf90_noerr .and. ncerr /= -39) then
     955                 :           0 :    NCF_CHECK(ncerr)
     956                 :             :  else
     957                 :      214898 :    ncerr = nf90_noerr
     958                 :             :  end if
     959                 :             : 
     960                 :      214898 : end function nctk_set_defmode
     961                 :             : !!***
     962                 :             : 
     963                 :             : !----------------------------------------------------------------------
     964                 :             : 
     965                 :             : !!****f* m_nctk/nctk_set_datamode
     966                 :             : !! NAME
     967                 :             : !!  nctk_set_datamode
     968                 :             : !!
     969                 :             : !! FUNCTION
     970                 :             : !!  Set the file in data mode. Return exit status
     971                 :             : !!
     972                 :             : !! INPUTS
     973                 :             : !!  ncid=Netcdf identifier.
     974                 :             : !!  [reserve]
     975                 :             : !!
     976                 :             : !! OUTPUT
     977                 :             : !!  ncerr=Exit status
     978                 :             : !!
     979                 :             : !! SOURCE
     980                 :             : 
     981                 :      141757 : integer function nctk_set_datamode(ncid, reserve) result(ncerr)
     982                 :             : 
     983                 :             : !Arguments ------------------------------------
     984                 :             :  integer,intent(in) :: ncid
     985                 :             :  logical,intent(in),optional :: reserve
     986                 :             : 
     987                 :             : !Local variables-------------------------------
     988                 :             : !scalars
     989                 :             :  logical :: do_reserve
     990                 :             : ! *********************************************************************
     991                 :             : 
     992                 :      141757 :  do_reserve = .False.; if (present(reserve)) do_reserve = reserve
     993                 :             : 
     994                 :      141757 :  ncerr = nf90_enddef(ncid)
     995                 :             : 
     996                 :             :  ! Use same trick as in etsf_io
     997                 :             :  ! needed otherwise netcdf complains if the file is already in def mode.
     998         [ -  + ]:      141757 :  if (ncerr /= nf90_noerr .and. ncerr /= -38) then
     999                 :           0 :    NCF_CHECK(ncerr)
    1000                 :             :  else
    1001                 :      141757 :    ncerr = nf90_noerr
    1002                 :             :  end if
    1003                 :             : 
    1004                 :      141757 :  return
    1005                 :             : 
    1006                 :             :  ! TODO
    1007                 :             :  if (do_reserve) then
    1008                 :             :    ncerr = nf90_enddef(ncid)
    1009                 :             :    !ncerr = nf90__enddef(ncid)
    1010                 :             :  else
    1011                 :             :    ncerr = nf90_enddef(ncid)
    1012                 :             :  end if
    1013                 :             : 
    1014                 :             : end function nctk_set_datamode
    1015                 :             : !!***
    1016                 :             : 
    1017                 :             : !----------------------------------------------------------------------
    1018                 :             : 
    1019                 :             : !!****f* m_nctk/nctk_set_collective
    1020                 :             : !! NAME
    1021                 :             : !!  nctk_set_collective
    1022                 :             : !!
    1023                 :             : !! FUNCTION
    1024                 :             : !!  Use collective IO for the given netcdf variable. Return exit status.
    1025                 :             : !!
    1026                 :             : !! INPUTS
    1027                 :             : !!  ncid=Netcdf file identifier.
    1028                 :             : !!  varid=Netcdf variable identifier.
    1029                 :             : !!  [independent]=True of use indepedent mode.
    1030                 :             : !!
    1031                 :             : !! SOURCE
    1032                 :             : 
    1033                 :      102598 : integer function nctk_set_collective(ncid, varid, independent) result(ncerr)
    1034                 :             : 
    1035                 :             : !Arguments ------------------------------------
    1036                 :             :  integer,intent(in) :: ncid, varid
    1037                 :             :  logical,optional,intent(in) :: independent
    1038                 :             : 
    1039                 :             : !Local variables-------------------------------
    1040                 :             :  logical :: independent__
    1041                 :             : ! *********************************************************************
    1042                 :             : 
    1043                 :      102598 :   ncerr = nf90_einval
    1044                 :      102338 :   independent__ = .false.
    1045                 :             : #ifdef HAVE_NETCDF_MPI
    1046         [ -  + ]:      102338 :   if (present(independent)) independent__ = independent
    1047         [ #  # ]:           0 :   if (independent__) then
    1048                 :           0 :     ncerr = nf90_var_par_access(ncid, varid, nf90_independent)
    1049                 :             :   else
    1050                 :      102338 :     ncerr = nf90_var_par_access(ncid, varid, nf90_collective)
    1051                 :             :   end if
    1052                 :             : #else
    1053                 :             :   ABI_ERROR("nctk_set_collective should not be called if NETCDF does not support MPI-IO")
    1054                 :             :   ABI_UNUSED((/ncid, varid/))
    1055                 :             : #endif
    1056                 :             : 
    1057                 :      102338 : end function nctk_set_collective
    1058                 :             : !!***
    1059                 :             : 
    1060                 :             : !!****f* m_nctk/nctk_def_one_dim
    1061                 :             : !! NAME
    1062                 :             : !!  nctk_def_one_dim
    1063                 :             : !!
    1064                 :             : !! FUNCTION
    1065                 :             : !!  Define list of dimensions variables and write their values.
    1066                 :             : !!  Return immediately if error
    1067                 :             : !!
    1068                 :             : !! INPUTS
    1069                 :             : !!  ncid=Netcdf identifier.
    1070                 :             : !!  dimnames(:)=List of strings with the name of the dimensions
    1071                 :             : !!  values(:)=List of integer scalars
    1072                 :             : !!  [defmode]=If True, the nc file is set in define mode (default=False)
    1073                 :             : !!  [prefix]=Prefix added to varnames and dimensions. Empty string if not specified.
    1074                 :             : !!
    1075                 :             : !! SOURCE
    1076                 :             : 
    1077                 :     1344487 : integer function nctk_def_one_dim(ncid, nctkdim, defmode, prefix) result(ncerr)
    1078                 :             : 
    1079                 :             : !Arguments ------------------------------------
    1080                 :             : !scalars
    1081                 :             :  integer,intent(in) :: ncid
    1082                 :             :  logical,optional,intent(in) :: defmode
    1083                 :             :  character(len=*),optional,intent(in) :: prefix
    1084                 :             : !arrays
    1085                 :             :  type(nctkdim_t),intent(in) :: nctkdim
    1086                 :             : 
    1087                 :             : !Local variables-------------------------------
    1088                 :             :  integer :: dimid,dimlen
    1089                 :             :  character(len=nctk_slen) :: dname
    1090                 :             :  character(len=500) :: msg
    1091                 :             : ! *********************************************************************
    1092                 :             : 
    1093                 :     1344487 :  ncerr = nf90_noerr
    1094                 :             : 
    1095         [ -  + ]:     1344487 :  if (present(defmode)) then
    1096         [ #  # ]:           0 :    if (defmode) then
    1097         [ #  # ]:           0 :      NCF_CHECK(nctk_set_defmode(ncid))
    1098                 :             :    end if
    1099                 :             :  end if
    1100                 :             : 
    1101         [ +  + ]:     1344487 :  if (present(prefix)) then
    1102   [ +  +  +  -  :         396 :    if (any(nctkdim%name == NCTK_IMPLICIT_DIMS)) then
                   -  + ]
    1103                 :           0 :      dname = nctkdim%name
    1104                 :             :    else
    1105         [ +  - ]:          36 :      dname = strcat(prefix, nctkdim%name)
    1106                 :             :    end if
    1107                 :             :  else
    1108                 :     1344451 :    dname = nctkdim%name
    1109                 :             :  end if
    1110                 :             : 
    1111                 :             :  ! if dimension already exists, test whether it has the same value else define new dim.
    1112                 :     1344487 :  ncerr = nf90_inq_dimid(ncid, dname, dimid)
    1113                 :             : 
    1114         [ +  + ]:     1344487 :  if (ncerr == nf90_noerr) then
    1115         [ -  + ]:      512338 :    NCF_CHECK(nf90_inquire_dimension(ncid, dimid, len=dimlen))
    1116         [ -  + ]:      512338 :    if (dimlen /= nctkdim%value) then
    1117                 :             :      write(msg, "(4a,2(a,i0))")&
    1118                 :           0 :         "dimension ", trim(dname)," already exists but with a different value",ch10,&
    1119                 :           0 :         "from file: ", dimlen, "; about to write: ", nctkdim%value
    1120                 :           0 :      ABI_ERROR(msg)
    1121                 :             :    end if
    1122                 :             :  else
    1123                 :      832149 :    ncerr = nf90_def_dim(ncid, dname, nctkdim%value, dimid)
    1124         [ -  + ]:      832149 :    NCF_CHECK(ncerr)
    1125                 :             :  end if
    1126                 :             : 
    1127                 :     1344487 : end function nctk_def_one_dim
    1128                 :             : !!***
    1129                 :             : 
    1130                 :             : !----------------------------------------------------------------------
    1131                 :             : 
    1132                 :             : !!****f* m_nctk/nctk_def_dim_list
    1133                 :             : !! NAME
    1134                 :             : !!  nctk_def_dim_list
    1135                 :             : !!
    1136                 :             : !! FUNCTION
    1137                 :             : !!  Define list of dimensions variables and write their values.
    1138                 :             : !!  Return immediately if error
    1139                 :             : !!
    1140                 :             : !! INPUTS
    1141                 :             : !!  ncid=Netcdf identifier.
    1142                 :             : !!  dimnames(:)=List of strings with the name of the dimensions
    1143                 :             : !!  values(:)=List of integer scalars
    1144                 :             : !!  [defmode]=If True, the nc file is set in define mode (default=False)
    1145                 :             : !!  [prefix]=Prefix added to varnames and dimensions. Empty string if not specified.
    1146                 :             : !!
    1147                 :             : !! SOURCE
    1148                 :             : 
    1149         [ -  + ]:      219481 : integer function nctk_def_dim_list(ncid, nctkdims, defmode, prefix) result(ncerr)
    1150                 :             : 
    1151                 :             : !Arguments ------------------------------------
    1152                 :             : !scalars
    1153                 :             :  integer,intent(in) :: ncid
    1154                 :             :  logical,optional,intent(in) :: defmode
    1155                 :             :  character(len=*),optional,intent(in) :: prefix
    1156                 :             : !arrays
    1157                 :             :  type(nctkdim_t),intent(in) :: nctkdims(:)
    1158                 :             : 
    1159                 :             : !Local variables-------------------------------
    1160                 :             :  integer :: ii
    1161                 :             : ! *********************************************************************
    1162                 :             : 
    1163                 :      219481 :  ncerr = nf90_noerr
    1164         [ +  + ]:      219481 :  if (present(defmode)) then
    1165         [ +  - ]:      105870 :    if (defmode) then
    1166         [ -  + ]:      105870 :      NCF_CHECK(nctk_set_defmode(ncid))
    1167                 :             :    end if
    1168                 :             :  end if
    1169                 :             : 
    1170         [ +  + ]:     1539590 :  do ii=1,size(nctkdims)
    1171         [ +  + ]:     1320109 :    if (present(prefix)) then
    1172                 :          36 :      ncerr = nctk_def_one_dim(ncid, nctkdims(ii), prefix=prefix)
    1173                 :             :    else
    1174                 :     1320073 :      ncerr = nctk_def_one_dim(ncid, nctkdims(ii))
    1175                 :             :    end if
    1176         [ -  + ]:     1539590 :    if (ncerr /= nf90_noerr) return
    1177                 :             :  end do
    1178                 :             : 
    1179                 :      219481 : end function nctk_def_dim_list
    1180                 :             : !!***
    1181                 :             : 
    1182                 :             : !----------------------------------------------------------------------
    1183                 :             : 
    1184                 :             : !!****f* m_nctk/nctk_set_atomic_units
    1185                 :             : !! NAME
    1186                 :             : !!  nctk_set_atomic_units
    1187                 :             : !!
    1188                 :             : !! FUNCTION
    1189                 :             : !!  Set the attributes "units" to "atomic units" and "scale_to_atomic_units" to one.
    1190                 :             : !!
    1191                 :             : !! INPUTS
    1192                 :             : !!  ncid=Netcdf identifier.
    1193                 :             : !!  varname=Name of the variable
    1194                 :             : !!
    1195                 :             : !! SOURCE
    1196                 :             : 
    1197                 :       97726 : integer function nctk_set_atomic_units(ncid, varname) result(ncerr)
    1198                 :             : 
    1199                 :             : !Arguments ------------------------------------
    1200                 :             :  integer,intent(in) :: ncid
    1201                 :             :  character(len=*),intent(in) :: varname
    1202                 :             : 
    1203                 :             : !Local variables-------------------------------
    1204                 :             :  integer :: varid
    1205                 :             : ! *********************************************************************
    1206                 :             : 
    1207                 :       97726 :  ncerr = nf90_noerr
    1208                 :             : 
    1209                 :       97726 :  varid = nctk_idname(ncid, varname)
    1210         [ -  + ]:       97726 :  NCF_CHECK(nf90_put_att(ncid, varid, "units", "atomic units"))
    1211         [ -  + ]:       97726 :  NCF_CHECK(nf90_put_att(ncid, varid, "scale_to_atomic_units", one))
    1212                 :             : 
    1213                 :       97726 : end function nctk_set_atomic_units
    1214                 :             : !!***
    1215                 :             : 
    1216                 :             : !----------------------------------------------------------------------
    1217                 :             : 
    1218                 :             : !!****f* m_nctk/nctk_def_basedims
    1219                 :             : !! NAME
    1220                 :             : !!  nctk_def_basedims
    1221                 :             : !!
    1222                 :             : !! FUNCTION
    1223                 :             : !!  Define the basic dimensions used in ETSF-IO files.
    1224                 :             : !!
    1225                 :             : !! INPUTS
    1226                 :             : !!  ncid=Netcdf identifier.
    1227                 :             : !!  [defmode]=If True, the nc file is set in define mode (default=False)
    1228                 :             : !!
    1229                 :             : !! SOURCE
    1230                 :             : 
    1231                 :       34569 : integer function nctk_def_basedims(ncid, defmode) result(ncerr)
    1232                 :             : 
    1233                 :             : !Arguments ------------------------------------
    1234                 :             :  integer,intent(in) :: ncid
    1235                 :             :  logical,optional,intent(in) :: defmode
    1236                 :             : ! *********************************************************************
    1237                 :             : 
    1238                 :       34569 :  ncerr = nf90_noerr
    1239                 :             : 
    1240         [ +  + ]:       34569 :  if (present(defmode)) then
    1241         [ +  - ]:       32624 :    if (defmode) then
    1242         [ -  + ]:       32624 :      NCF_CHECK(nctk_set_defmode(ncid))
    1243                 :             :    end if
    1244                 :             :  end if
    1245                 :             : 
    1246                 :             :  ! Basic ETSF-IO dimensions that should be always present in the file.
    1247                 :             :  ncerr = nctk_def_dims(ncid, [&
    1248                 :             :    nctkdim_t("complex", 2), nctkdim_t("symbol_length", 2), nctkdim_t("character_string_length", etsfio_charlen),&
    1249                 :             :    nctkdim_t("number_of_cartesian_directions", 3), nctkdim_t("number_of_reduced_dimensions", 3),&
    1250                 :             :    nctkdim_t("number_of_vectors", 3) &
    1251         [ +  + ]:      241983 :  ])
    1252         [ -  + ]:       34569 :  NCF_CHECK(ncerr)
    1253                 :             : 
    1254                 :             :  ! Useful integers.
    1255                 :             :  ncerr = nctk_def_dims(ncid, [ &
    1256                 :             :    nctkdim_t("one", 1), nctkdim_t("two", 2), nctkdim_t("three", 3), &
    1257                 :             :    nctkdim_t("four", 4), nctkdim_t("five", 5), nctkdim_t("six", 6), &
    1258                 :             :    nctkdim_t("seven", 7), nctkdim_t("eight", 8), nctkdim_t("nine", 9), nctkdim_t("ten", 10), &
    1259                 :             :    nctkdim_t("fnlen", fnlen + 1) &
    1260         [ +  + ]:      414828 :  ])
    1261         [ -  + ]:       34569 :  NCF_CHECK(ncerr)
    1262                 :             : 
    1263                 :       34569 : end function nctk_def_basedims
    1264                 :             : !!***
    1265                 :             : 
    1266                 :             : !!****f* m_nctk/ab_define_var
    1267                 :             : !!
    1268                 :             : !! NAME
    1269                 :             : !! ab_define_var
    1270                 :             : !!
    1271                 :             : !! FUNCTION
    1272                 :             : !! Write the definition of a variable, including units and mnemonics
    1273                 :             : !!
    1274                 :             : !! INPUTS
    1275                 :             : !! ncid = Identifier of the netcdf dataset
    1276                 :             : !! var_dim_id = Identifier of the Dimensions
    1277                 :             : !! var_id     = Identifier of the variable
    1278                 :             : !! var_mnemo  = String of mnemonics
    1279                 :             : !! var_name   = String with the name of the variable
    1280                 :             : !! var_type   = NetCDF type of variable (NF90_DOUBLE, etc)
    1281                 :             : !! var_units  = String of units
    1282                 :             : !!
    1283                 :             : !! OUTPUT
    1284                 :             : !!  (only writing)
    1285                 :             : !!
    1286                 :             : !! SOURCE
    1287                 :             : 
    1288         [ -  + ]:       17269 : subroutine ab_define_var(ncid, var_dim_id, var_id, var_type, var_name, var_mnemo, var_units)
    1289                 :             : 
    1290                 :             : !Arguments ------------------------------------
    1291                 :             : !scalars
    1292                 :             :  integer, intent(in) :: ncid
    1293                 :             :  integer, intent(out) :: var_id
    1294                 :             :  character(len=*), intent(in) :: var_mnemo,var_units,var_name
    1295                 :             :  integer,intent(in) :: var_type
    1296                 :             : !arrays
    1297                 :             :  integer,intent(in) :: var_dim_id(:)
    1298                 :             : 
    1299                 :             : !Local variables-------------------------------
    1300                 :             :  integer :: ncerr
    1301                 :             : ! *************************************************************************
    1302                 :             : 
    1303                 :       17269 :  ncerr = nf90_def_var(ncid, trim(var_name), var_type, var_dim_id, var_id)
    1304   [ -  +  -  - ]:       17269 :  NCF_CHECK_MSG(ncerr," define variable "//trim(var_name))
    1305                 :             : 
    1306                 :       17269 :  ncerr = nf90_put_att(ncid, var_id,  "units",trim(var_units))
    1307   [ -  +  -  - ]:       17269 :  NCF_CHECK_MSG(ncerr," define attribute for "//trim(var_name))
    1308                 :             : 
    1309                 :       17269 :  ncerr = nf90_put_att(ncid, var_id,  "mnemonics", trim(var_mnemo))
    1310   [ -  +  -  - ]:       17269 :  NCF_CHECK_MSG(ncerr," define attribute for "//trim(var_name))
    1311                 :             : 
    1312                 :       17269 : end subroutine ab_define_var
    1313                 :             : !!***
    1314                 :             : 
    1315                 :             : !!****f* m_nctk/nctk_def_scalars_type
    1316                 :             : !! NAME
    1317                 :             : !!  nctk_def_scalars_type
    1318                 :             : !!
    1319                 :             : !! FUNCTION
    1320                 :             : !!  Define list of **scalar** variables with a given type, Return immediately if error
    1321                 :             : !!
    1322                 :             : !! INPUTS
    1323                 :             : !!  ncid=Netcdf identifier.
    1324                 :             : !!  varnames(:)=List of strings with the name of the variables
    1325                 :             : !!  xtype=Type of the variables
    1326                 :             : !!  [defmode]=If True, the nc file is set in define mode (default=False)
    1327                 :             : !!  [prefix]=Prefix added to varnames and dimensions. Empty string if not specified.
    1328                 :             : !!
    1329                 :             : !! SOURCE
    1330                 :             : 
    1331         [ -  + ]:      216230 : integer function nctk_def_scalars_type(ncid, varnames, xtype, defmode, prefix) result(ncerr)
    1332                 :             : 
    1333                 :             : !Arguments ------------------------------------
    1334                 :             : !scalars
    1335                 :             :  integer,intent(in) :: ncid,xtype
    1336                 :             :  logical,optional,intent(in) :: defmode
    1337                 :             :  character(len=*),optional,intent(in) :: prefix
    1338                 :             : !arrays
    1339                 :             :  character(len=*),intent(in) :: varnames(:)
    1340                 :             : 
    1341                 :             : !Local variables-------------------------------
    1342                 :             : !scalars
    1343                 :             :  integer :: ii,varid
    1344                 :             :  character(len=nctk_slen) :: vname
    1345                 :             :  type(nctkvar_t) :: var
    1346                 :             : ! *********************************************************************
    1347                 :             : 
    1348                 :      216230 :  ncerr = nf90_noerr
    1349                 :      216230 :  if (present(defmode)) then
    1350         [ +  - ]:       39766 :    if (defmode) then
    1351         [ -  + ]:       39766 :      NCF_CHECK(nctk_set_defmode(ncid))
    1352                 :             :    end if
    1353                 :             :  end if
    1354                 :             : 
    1355                 :             :  ! Special case where dimension is null
    1356         [ +  + ]:     1155271 :  do ii=1,size(varnames)
    1357         [ +  + ]:      939041 :    vname = varnames(ii)
    1358   [ +  +  +  - ]:      939041 :    if (present(prefix)) vname = strcat(prefix, vname)
    1359                 :             : 
    1360         [ +  + ]:     1155271 :    if (nf90_inq_varid(ncid, vname, varid) == nf90_noerr)  then
    1361                 :             :        ! Variable already exists. Check if type and dimensions agree
    1362                 :       99038 :        call var_from_id(ncid, varid, var)
    1363                 :             : 
    1364   [ +  -  -  + ]:       99038 :        if (.not. (var%xtype == xtype .and. var%ndims == 0)) then
    1365                 :           0 :          ABI_ERROR("variable already exists with a different definition.")
    1366                 :             :        else
    1367                 :             :          cycle ! Dimension matches, skip definition.
    1368                 :             :        end if
    1369                 :             : 
    1370                 :             :    else
    1371                 :             :      ! Define variable since it doesn't exist.
    1372                 :      840003 :      ncerr = nf90_def_var(ncid, vname, xtype, varid)
    1373         [ -  + ]:      840003 :      NCF_CHECK(ncerr)
    1374                 :             :    end if
    1375                 :             :  end do
    1376                 :             : 
    1377   [ +  +  +  +  :   443055270 : end function nctk_def_scalars_type
                   +  + ]
    1378                 :             : !!***
    1379                 :             : 
    1380                 :             : !!****f* m_nctk/nctk_def_iscalars
    1381                 :             : !! NAME
    1382                 :             : !!  nctk_def_iscalars
    1383                 :             : !!
    1384                 :             : !! FUNCTION
    1385                 :             : !!  Define list of integer **scalar** variables. Return immediately if error
    1386                 :             : !!
    1387                 :             : !! INPUTS
    1388                 :             : !!  ncid=Netcdf identifier.
    1389                 :             : !!  varnames(:)=List of strings with the name of the variables
    1390                 :             : !!  [defmode]=If True, the nc file is set in define mode (default=False)
    1391                 :             : !!  [prefix]=Prefix added to varnames and dimensions. Empty string if not specified.
    1392                 :             : !!
    1393                 :             : !! SOURCE
    1394                 :             : 
    1395         [ -  + ]:      112221 : integer function nctk_def_iscalars(ncid, varnames, defmode, prefix) result(ncerr)
    1396                 :             : 
    1397                 :             : !Arguments ------------------------------------
    1398                 :             : !scalars
    1399                 :             :  integer,intent(in) :: ncid
    1400                 :             :  logical,optional,intent(in) :: defmode
    1401                 :             :  character(len=*),optional,intent(in) :: prefix
    1402                 :             : !arrays
    1403                 :             :  character(len=*),intent(in) :: varnames(:)
    1404                 :             : ! *********************************************************************
    1405                 :             : 
    1406         [ +  + ]:      112221 :  if (present(defmode)) then
    1407                 :       28877 :    ncerr = nctk_def_scalars_type(ncid, varnames, nf90_int, defmode=defmode)
    1408                 :             :  else
    1409         [ +  + ]:       83344 :    if (present(prefix)) then
    1410                 :          36 :      ncerr = nctk_def_scalars_type(ncid, varnames, nf90_int, prefix=prefix)
    1411                 :             :    else
    1412                 :       83308 :      ncerr = nctk_def_scalars_type(ncid, varnames, nf90_int)
    1413                 :             :    end if
    1414                 :             :  end if
    1415                 :             : 
    1416                 :      112221 : end function nctk_def_iscalars
    1417                 :             : !!***
    1418                 :             : 
    1419                 :             : !!****f* m_nctk/nctk_def_dpscalars
    1420                 :             : !! NAME
    1421                 :             : !!  nctk_def_dpscalars
    1422                 :             : !!
    1423                 :             : !! FUNCTION
    1424                 :             : !!  Define list of double precision **scalar** variables. Return immediately if error
    1425                 :             : !!
    1426                 :             : !! INPUTS
    1427                 :             : !!  ncid=Netcdf identifier.
    1428                 :             : !!  varnames(:)=List of strings with the name of the variables
    1429                 :             : !!  [defmode]=If True, the nc file is set in define mode (default=False)
    1430                 :             : !!  [prefix]=Prefix added to varnames and dimensions. Empty string if not specified.
    1431                 :             : !!
    1432                 :             : !! SOURCE
    1433                 :             : 
    1434                 :      208018 : integer function nctk_def_dpscalars(ncid, varnames, defmode, prefix) result(ncerr)
    1435                 :             : 
    1436                 :             : !Arguments ------------------------------------
    1437                 :             : !scalars
    1438                 :             :  integer,intent(in) :: ncid
    1439                 :             :  logical,optional,intent(in) :: defmode
    1440                 :             :  character(len=*),optional,intent(in) :: prefix
    1441                 :             : !arrays
    1442                 :             :  character(len=*),intent(in) :: varnames(:)
    1443                 :             : 
    1444                 :             : !Local variables-------------------------------
    1445                 :             :  character(len=nctk_slen) :: prefix_
    1446                 :             : ! *********************************************************************
    1447   [ +  +  -  + ]:      104009 :  prefix_ = ""; if (present(prefix)) prefix_ = prefix
    1448                 :             : 
    1449         [ +  + ]:      104009 :  if (present(defmode)) then
    1450                 :       10889 :    ncerr = nctk_def_scalars_type(ncid, varnames, nf90_double, defmode=defmode, prefix=prefix_)
    1451                 :             :  else
    1452                 :       93120 :    ncerr = nctk_def_scalars_type(ncid, varnames, nf90_double, prefix=prefix_)
    1453                 :             :  end if
    1454                 :             : 
    1455         [ -  + ]:      104009 : end function nctk_def_dpscalars
    1456                 :             : !!***
    1457                 :             : 
    1458                 :             : !!****f* m_nctk/nctk_def_one_array
    1459                 :             : !! NAME
    1460                 :             : !!  nctk_def_one_array
    1461                 :             : !!
    1462                 :             : !! FUNCTION
    1463                 :             : !!  Define list of arrays with a given type, Return immediately if error
    1464                 :             : !!
    1465                 :             : !! INPUTS
    1466                 :             : !!  ncid=Netcdf identifier.
    1467                 :             : !!  nctk_array=Array descriptor.
    1468                 :             : !!  [defmode]=If True, the nc file is set in define mode (default=False)
    1469                 :             : !!  [prefix]=Prefix added to varnames and dimensions. Empty string if not specified.
    1470                 :             : !!
    1471                 :             : !! SOURCE
    1472                 :             : 
    1473                 :             : 
    1474                 :     1201761 : integer function nctk_def_one_array(ncid, nctk_array, defmode, varid, prefix) result(ncerr)
    1475                 :             : 
    1476                 :             : !Arguments ------------------------------------
    1477                 :             : !scalars
    1478                 :             :  integer,intent(in) :: ncid
    1479                 :             :  logical,optional,intent(in) :: defmode
    1480                 :             :  integer,optional,intent(out) :: varid
    1481                 :             :  type(nctkarr_t),intent(in) :: nctk_array
    1482                 :             :  character(len=*),optional,intent(in) :: prefix
    1483                 :             : 
    1484                 :             : !Local variables-------------------------------
    1485                 :             : !scalars
    1486                 :             :  integer :: ii,xtype,prev,cnt,nn,vid
    1487                 :             :  character(len=500) :: msg
    1488                 :             : !arrays
    1489                 :             :  integer :: dimids(NF90_MAX_DIMS),dimvals(NF90_MAX_DIMS)
    1490                 :             :  character(len=nctk_slen) :: sarr(NF90_MAX_DIMS), string, pre, vname, dimname
    1491                 :             :  type(nctkvar_t) :: var
    1492                 :             : ! *********************************************************************
    1493                 :             : 
    1494         [ -  + ]:          90 :  pre = ""; if (present(prefix)) pre = prefix
    1495                 :             : 
    1496                 :     1201761 :  ncerr = nf90_noerr
    1497         [ -  + ]:     1201761 :  if (present(defmode)) then
    1498         [ #  # ]:           0 :    if (defmode) then
    1499         [ #  # ]:           0 :      NCF_CHECK(nctk_set_defmode(ncid))
    1500                 :             :    end if
    1501                 :             :  end if
    1502                 :             : 
    1503                 :     1201761 :  xtype = str2xtype(nctk_array%dtype)
    1504         [ +  - ]:     1201761 :  vname = strcat(pre, nctk_array%name)
    1505                 :             : 
    1506                 :             :  ! Build array of strings with the dimensions.
    1507                 :     1201761 :  string = nctk_array%shape_str
    1508                 :     1201761 :  nn = char_count(string, ",")
    1509         [ -  + ]:     1201761 :  ABI_CHECK(nn <= NF90_MAX_DIMS, "Too many dimensions!")
    1510                 :             : 
    1511                 :             :  ! Parse dimension names and add prefix (if any).
    1512         [ +  + ]:     1201761 :  if (nn == 0) then
    1513                 :      557958 :    cnt = 1
    1514                 :      557958 :    dimname = lstrip(string)
    1515   [ +  +  +  +  :     6060248 :    if (any(dimname == NCTK_IMPLICIT_DIMS)) then
                   +  + ]
    1516                 :       10941 :      sarr(1) = dimname
    1517                 :             :    else
    1518         [ +  - ]:      547017 :      sarr(1) = strcat(pre, dimname)
    1519                 :             :    end if
    1520                 :             :  else
    1521                 :      643803 :    prev = 0; cnt = 0
    1522         [ +  + ]:    34841515 :    do ii=1,len_trim(string)
    1523         [ +  + ]:    34841515 :      if (string(ii:ii) == ",") then
    1524                 :      982150 :        cnt = cnt + 1
    1525         [ +  - ]:      982150 :        dimname = lstrip(string(prev+1:ii-1))
    1526   [ +  +  +  +  :    10071042 :        if (any(dimname == NCTK_IMPLICIT_DIMS)) then
                   +  + ]
    1527                 :       93686 :          sarr(cnt) = dimname
    1528                 :             :        else
    1529         [ +  - ]:      888464 :          sarr(cnt) = strcat(pre, dimname)
    1530                 :             :        end if
    1531                 :             :        prev = ii
    1532                 :             :      end if
    1533                 :             :    end do
    1534                 :      643803 :    cnt = cnt + 1
    1535         [ +  - ]:      643803 :    dimname = lstrip(string(prev+1:ii-1))
    1536   [ +  +  +  +  :     7078940 :    if (any(dimname == NCTK_IMPLICIT_DIMS)) then
                   +  + ]
    1537                 :         393 :      sarr(cnt) = dimname
    1538                 :             :    else
    1539         [ +  - ]:      643410 :      sarr(cnt) = strcat(pre, dimname)
    1540                 :             :    end if
    1541                 :             :  end if
    1542                 :             : 
    1543                 :             :  ! Get dimids
    1544         [ +  + ]:     3385672 :  do ii=1,cnt
    1545         [ -  + ]:     2183911 :    NCF_CHECK_MSG(nf90_inq_dimid(ncid, sarr(ii), dimids(ii)), sarr(ii))
    1546         [ -  + ]:     3385672 :    NCF_CHECK(nf90_inquire_dimension(ncid, dimids(ii), len=dimvals(ii)))
    1547                 :             :  end do
    1548                 :             : 
    1549                 :             :  ! Check if dimension already exists.
    1550                 :             :  ! Variable already exists. Check if type and dimensions agree
    1551         [ +  + ]:     1201761 :  if (nf90_inq_varid(ncid, vname, vid) == nf90_noerr)  then
    1552                 :      225766 :    call var_from_id(ncid, vid, var)
    1553   [ +  -  -  + ]:      225766 :    if (.not. (var%xtype == xtype .and. var%ndims == cnt)) then
    1554                 :             :       write(msg,"(4a,2(2(a,i0),a))")&
    1555                 :           0 :         "variable ",trim(vname)," already exists with a different definition:",ch10,&
    1556                 :           0 :         "In file:     xtype = ",var%xtype,", ndims = ",var%ndims,ch10,&
    1557                 :           0 :         "From caller: xtype = ",xtype,", ndims = ",cnt,ch10
    1558                 :           0 :       ABI_ERROR(msg)
    1559                 :             :    end if
    1560   [ +  +  +  -  :      641771 :    if (any(dimvals(1:cnt) /= var%dimlens(1:var%ndims))) then
                   -  + ]
    1561                 :             :       write(msg,"(4a,2(3a))")&
    1562                 :           0 :         "variable ",trim(vname)," already exists but with different shape.",ch10,&
    1563         [ #  # ]:           0 :         "In file:     dims = ",trim(ltoa(var%dimlens(:var%ndims))),ch10,&
    1564         [ #  # ]:           0 :         "From caller  dims = ",trim(ltoa(dimvals(:cnt))),ch10
    1565                 :           0 :       ABI_ERROR(msg)
    1566                 :             :    end if
    1567         [ -  + ]:      225766 :    if (present(varid)) varid = vid
    1568                 :      225766 :    return
    1569                 :             :  end if
    1570                 :             : 
    1571                 :             :  ! Define variable since it doesn't exist.
    1572                 :      975995 :  ncerr = nf90_def_var(ncid, vname, xtype, dimids(1:cnt), vid)
    1573         [ -  + ]:      975995 :  NCF_CHECK(ncerr)
    1574                 :             : 
    1575         [ +  + ]:      975995 :  if (present(varid)) varid = vid
    1576                 :             : 
    1577   [ +  +  +  +  :  2463384284 : end function nctk_def_one_array
                   +  + ]
    1578                 :             : !!***
    1579                 :             : 
    1580                 :             : !!****f* m_nctk/nctk_def_array_list
    1581                 :             : !! NAME
    1582                 :             : !!  nctk_def_array_list
    1583                 :             : !!
    1584                 :             : !! FUNCTION
    1585                 :             : !!  Define list of arrays with a given type, Return immediately if error
    1586                 :             : !!
    1587                 :             : !! INPUTS
    1588                 :             : !!  ncid=Netcdf identifier.
    1589                 :             : !!  nctk_arrays(:)=List of array descriptors.
    1590                 :             : !!  [defmode]=If True, the nc file is set in define mode (default=False)
    1591                 :             : !!  [prefix]=Prefix added to varnames and dimensions. Empty string if not specified.
    1592                 :             : !!
    1593                 :             : !! SOURCE
    1594                 :             : 
    1595                 :             : 
    1596         [ -  + ]:      247715 : integer function nctk_def_array_list(ncid, nctk_arrays, defmode, prefix) result(ncerr)
    1597                 :             : 
    1598                 :             : !Arguments ------------------------------------
    1599                 :             : !scalars
    1600                 :             :  integer,intent(in) :: ncid
    1601                 :             :  logical,optional,intent(in) :: defmode
    1602                 :             :  character(len=*),optional,intent(in) :: prefix
    1603                 :             : !arrays
    1604                 :             :  type(nctkarr_t),intent(in) :: nctk_arrays(:)
    1605                 :             : 
    1606                 :             : !Local variables-------------------------------
    1607                 :             :  integer :: ia
    1608                 :             : ! *********************************************************************
    1609                 :             : 
    1610                 :      247715 :  ncerr = nf90_noerr
    1611         [ +  + ]:      247715 :  if (present(defmode)) then
    1612         [ +  - ]:        4365 :    if (defmode) then
    1613         [ -  + ]:        4365 :      NCF_CHECK(nctk_set_defmode(ncid))
    1614                 :             :    end if
    1615                 :             :  end if
    1616                 :             : 
    1617         [ +  + ]:     1335919 :  do ia=1,size(nctk_arrays)
    1618         [ +  + ]:     1335919 :    if (present(prefix)) then
    1619         [ -  + ]:          90 :      NCF_CHECK(nctk_def_one_array(ncid, nctk_arrays(ia), prefix=prefix))
    1620                 :             :    else
    1621         [ -  + ]:     1088114 :      NCF_CHECK(nctk_def_one_array(ncid, nctk_arrays(ia)))
    1622                 :             :    end if
    1623                 :             :  end do
    1624                 :             : 
    1625                 :      247715 : end function nctk_def_array_list
    1626                 :             : !!***
    1627                 :             : 
    1628                 :             : !!****f* m_nctk/nctk_write_iscalars
    1629                 :             : !! NAME
    1630                 :             : !!  nctk_write_iscalars
    1631                 :             : !!
    1632                 :             : !! FUNCTION
    1633                 :             : !!  Write a list of **scalar** integer variables. Return immediately if error
    1634                 :             : !!
    1635                 :             : !! INPUTS
    1636                 :             : !!  ncid=Netcdf identifier.
    1637                 :             : !!  varnames(:)=List of strings with the name of the variables
    1638                 :             : !!  values(:)=List of integer scalars
    1639                 :             : !!  [datamode]=If True, the nc file is set in data mode (default=False)
    1640                 :             : !!
    1641                 :             : !! OUTPUT
    1642                 :             : !!  ncerr=Exit status
    1643                 :             : !!
    1644                 :             : !! SOURCE
    1645                 :             : 
    1646   [ -  +  -  + ]:       40779 : integer function nctk_write_iscalars(ncid, varnames, values, datamode) result(ncerr)
    1647                 :             : 
    1648                 :             : !Arguments ------------------------------------
    1649                 :             : !scalars
    1650                 :             :  integer,intent(in) :: ncid
    1651                 :             :  logical,optional,intent(in) :: datamode
    1652                 :             : !arrays
    1653                 :             :  integer,intent(in) :: values(:)
    1654                 :             :  character(len=*),intent(in) :: varnames(:)
    1655                 :             : 
    1656                 :             : !Local variables-------------------------------
    1657                 :             :  integer :: ii,varid
    1658                 :             : ! *********************************************************************
    1659                 :             : 
    1660         [ -  + ]:       40779 :  ABI_CHECK(size(varnames) == size(values), "Different size in varnames, values")
    1661                 :             : 
    1662                 :       40779 :  ncerr = nf90_noerr
    1663         [ +  + ]:       40779 :  if (present(datamode)) then
    1664         [ +  - ]:          14 :    if (datamode) then
    1665         [ -  + ]:          14 :      NCF_CHECK(nctk_set_datamode(ncid))
    1666                 :             :    end if
    1667                 :             :  end if
    1668                 :             : 
    1669         [ +  + ]:      245300 :  do ii=1,size(varnames)
    1670         [ -  + ]:      204521 :    NCF_CHECK_MSG(nf90_inq_varid(ncid, varnames(ii), varid), sjoin("Inquiring: ", varnames(ii)))
    1671         [ -  + ]:      245300 :    NCF_CHECK(nf90_put_var(ncid, varid, values(ii)))
    1672                 :             :  end do
    1673                 :             : 
    1674                 :       40779 : end function nctk_write_iscalars
    1675                 :             : !!***
    1676                 :             : 
    1677                 :             : !!****f* m_nctk/nctk_write_dpscalars
    1678                 :             : !! NAME
    1679                 :             : !!  nctk_write_dpscalars
    1680                 :             : !!
    1681                 :             : !! FUNCTION
    1682                 :             : !!  Write a list of **scalar** real(dp) variables. Return immediately if error
    1683                 :             : !!
    1684                 :             : !! INPUTS
    1685                 :             : !!  ncid=Netcdf identifier.
    1686                 :             : !!  varnames(:)=List of strings with the name of the variables
    1687                 :             : !!  values(:)=List of real(dp) scalars
    1688                 :             : !!  [datamode]=If True, the nc file is set in data mode (default=False)
    1689                 :             : !!
    1690                 :             : !! SOURCE
    1691                 :             : 
    1692   [ -  +  -  + ]:       37373 : integer function nctk_write_dpscalars(ncid, varnames, values, datamode) result(ncerr)
    1693                 :             : 
    1694                 :             : !Arguments ------------------------------------
    1695                 :             : !scalars
    1696                 :             :  integer,intent(in) :: ncid
    1697                 :             :  logical,optional,intent(in) :: datamode
    1698                 :             : !arrays
    1699                 :             :  real(dp),intent(in) :: values(:)
    1700                 :             :  character(len=*),intent(in) :: varnames(:)
    1701                 :             : 
    1702                 :             : !Local variables-------------------------------
    1703                 :             :  integer :: ii,varid
    1704                 :             : ! *********************************************************************
    1705                 :             : 
    1706                 :       37373 :  ncerr = nf90_noerr
    1707                 :             : 
    1708         [ -  + ]:       37373 :  ABI_CHECK(size(varnames) == size(values), "Different size in varnames, values")
    1709                 :             : 
    1710         [ +  + ]:       37373 :  if (present(datamode)) then
    1711         [ +  - ]:        4148 :    if (datamode) then
    1712         [ -  + ]:        4148 :      NCF_CHECK(nctk_set_datamode(ncid))
    1713                 :             :    end if
    1714                 :             :  end if
    1715                 :             : 
    1716         [ +  + ]:      270018 :  do ii=1,size(varnames)
    1717         [ -  + ]:      232645 :    NCF_CHECK(nf90_inq_varid(ncid, varnames(ii), varid))
    1718         [ -  + ]:      270018 :    NCF_CHECK(nf90_put_var(ncid, varid, values(ii)))
    1719                 :             :  end do
    1720                 :             : 
    1721                 :       37373 : end function nctk_write_dpscalars
    1722                 :             : !!***
    1723                 :             : 
    1724                 :             : !!****f* m_nctk/nctk_defnwrite_ivars
    1725                 :             : !! NAME
    1726                 :             : !!  nctk_defnwrite_ivars
    1727                 :             : !!
    1728                 :             : !! FUNCTION
    1729                 :             : !!  Define list of integer **scalar** variables and write their values.
    1730                 :             : !!  Return immediately if error
    1731                 :             : !!
    1732                 :             : !! INPUTS
    1733                 :             : !!  ncid=Netcdf identifier.
    1734                 :             : !!  varnames(:)=List of strings with the name of the variables
    1735                 :             : !!  values(:)=List of integer scalars
    1736                 :             : !!
    1737                 :             : !! SOURCE
    1738                 :             : 
    1739   [ -  +  -  + ]:       13558 : integer function nctk_defnwrite_ivars(ncid, varnames, values) result(ncerr)
    1740                 :             : 
    1741                 :             : !Arguments ------------------------------------
    1742                 :             : !scalars
    1743                 :             :  integer,intent(in) :: ncid
    1744                 :             : !arrays
    1745                 :             :  integer,intent(in) :: values(:)
    1746                 :             :  character(len=*),intent(in) :: varnames(:)
    1747                 :             : 
    1748                 :             : !Local variables-------------------------------
    1749                 :             : !scalars
    1750                 :             :  integer :: ii,varid
    1751                 :             : ! *********************************************************************
    1752                 :             : 
    1753         [ -  + ]:       13558 :  ABI_CHECK(size(varnames) == size(values), "Different size in varnames, values")
    1754                 :             : 
    1755                 :       13558 :  ncerr = nctk_def_iscalars(ncid, varnames, defmode=.True.)
    1756         [ -  + ]:       13558 :  NCF_CHECK(ncerr)
    1757                 :             : 
    1758         [ -  + ]:       13558 :  NCF_CHECK(nctk_set_datamode(ncid))
    1759         [ +  + ]:       39270 :  do ii=1,size(varnames)
    1760                 :       25712 :    varid = nctk_idname(ncid, varnames(ii))
    1761         [ -  + ]:       39270 :    NCF_CHECK(nf90_put_var(ncid, varid, values(ii)))
    1762                 :             :  end do
    1763                 :             : 
    1764                 :       13558 : end function nctk_defnwrite_ivars
    1765                 :             : !!***
    1766                 :             : 
    1767                 :             : !!****f* m_nctk/nctk_defnwrite_dpvars
    1768                 :             : !! NAME
    1769                 :             : !!  nctk_defnwrite_dpvars
    1770                 :             : !!
    1771                 :             : !! FUNCTION
    1772                 :             : !!  Define list of real(dp) **scalar** variables and write their values.
    1773                 :             : !!  Return immediately if error
    1774                 :             : !!
    1775                 :             : !! INPUTS
    1776                 :             : !!  ncid=Netcdf identifier.
    1777                 :             : !!  varnames(:)=List of strings with the name of the variables
    1778                 :             : !!  values(:)=List of integer scalars
    1779                 :             : !!
    1780                 :             : !! SOURCE
    1781                 :             : 
    1782   [ -  +  -  + ]:       10889 : integer function nctk_defnwrite_dpvars(ncid, varnames, values) result(ncerr)
    1783                 :             : 
    1784                 :             : !Arguments ------------------------------------
    1785                 :             : !scalars
    1786                 :             :  integer,intent(in) :: ncid
    1787                 :             : !arrays
    1788                 :             :  real(dp),intent(in) :: values(:)
    1789                 :             :  character(len=*),intent(in) :: varnames(:)
    1790                 :             : 
    1791                 :             : !Local variables-------------------------------
    1792                 :             : !scalars
    1793                 :             :  integer :: ii,varid
    1794                 :             : !arrays
    1795                 :             : ! *********************************************************************
    1796                 :             :  ncerr = nf90_noerr
    1797                 :             : 
    1798         [ -  + ]:       10889 :  ABI_CHECK(size(varnames) == size(values), "Different size in varnames, values")
    1799                 :             : 
    1800                 :       10889 :  ncerr = nctk_def_dpscalars(ncid, varnames, defmode=.True.)
    1801         [ -  + ]:       10889 :  NCF_CHECK(ncerr)
    1802                 :             : 
    1803         [ -  + ]:       10889 :  NCF_CHECK(nctk_set_datamode(ncid))
    1804         [ +  + ]:      244429 :  do ii=1,size(varnames)
    1805                 :             :    !write(std_out,*)varnames(ii)
    1806                 :      233540 :    varid = nctk_idname(ncid, varnames(ii))
    1807         [ -  + ]:      244429 :    NCF_CHECK(nf90_put_var(ncid, varid, values(ii)))
    1808                 :             :  end do
    1809                 :             : 
    1810                 :       10889 : end function nctk_defnwrite_dpvars
    1811                 :             : !!***
    1812                 :             : 
    1813                 :             : !!****f* m_nctk/nctk_write_ibz
    1814                 :             : !! NAME
    1815                 :             : !!  nctk_write_ibz
    1816                 :             : !!
    1817                 :             : !! FUNCTION
    1818                 :             : !!  Write the list of the k-points in the IBZ with the corresponding weights in Netcdf format.
    1819                 :             : !!  Mainly used for passing data to AbiPy. This routine should be called by master only.
    1820                 :             : !!
    1821                 :             : !! INPUTS
    1822                 :             : !!  fname=File name
    1823                 :             : !!  kpoints(:,:)=List of k-points
    1824                 :             : !!  weights(:)=K-point weights
    1825                 :             : !!
    1826                 :             : !! OUTPUT
    1827                 :             : !!  ncerr=Exit status
    1828                 :             : !!
    1829                 :             : !! SOURCE
    1830                 :             : 
    1831   [ #  #  #  # ]:           0 : integer function nctk_write_ibz(fname, kpoints, weights) result(ncerr)
    1832                 :             : 
    1833                 :             : !Arguments ------------------------------------
    1834                 :             : !scalars
    1835                 :             :  character(len=*),intent(in) :: fname
    1836                 :             : !arrays
    1837                 :             :  real(dp),intent(in) :: kpoints(:,:),weights(:)
    1838                 :             : 
    1839                 :             : !Local variables-------------------------------
    1840                 :             :  integer :: nkpts,ncid
    1841                 :             : ! *********************************************************************
    1842                 :             : 
    1843         [ #  # ]:           0 :  ABI_CHECK(size(kpoints, dim=2) == size(weights), "size(kpoints, dim=2) != size(weights)")
    1844                 :           0 :  nkpts = size(kpoints, dim=2)
    1845                 :             : 
    1846         [ #  # ]:           0 :  NCF_CHECK_MSG(nctk_open_create(ncid, fname, xmpi_comm_self), sjoin("Creating:", fname))
    1847                 :             : 
    1848                 :             :  ncerr = nctk_def_dims(ncid, [ &
    1849         [ #  # ]:           0 :    nctkdim_t("number_of_reduced_dimensions",3), nctkdim_t("number_of_kpoints", nkpts)], defmode=.True.)
    1850         [ #  # ]:           0 :  NCF_CHECK(ncerr)
    1851                 :             : 
    1852                 :             :  ncerr = nctk_def_array_list(ncid, [&
    1853                 :             :    nctkarr_t('reduced_coordinates_of_kpoints', "dp", "number_of_reduced_dimensions, number_of_kpoints"),&
    1854         [ #  # ]:           0 :    nctkarr_t('kpoint_weights', "dp", "number_of_kpoints")])
    1855                 :             :  NCF_CHECK(ncerr)
    1856                 :             : 
    1857         [ #  # ]:           0 :  NCF_CHECK(nctk_set_datamode(ncid))
    1858                 :             : 
    1859                 :           0 :  ncerr = nf90_put_var(ncid, nctk_idname(ncid, 'reduced_coordinates_of_kpoints'), kpoints)
    1860         [ #  # ]:           0 :  NCF_CHECK(ncerr)
    1861                 :             : 
    1862         [ #  # ]:           0 :  NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, 'kpoint_weights'), weights))
    1863                 :             : 
    1864         [ #  # ]:           0 :  NCF_CHECK(nf90_close(ncid))
    1865                 :             : 
    1866                 :           0 : end function nctk_write_ibz
    1867                 :             : !!***
    1868                 :             : 
    1869                 :             : !!****f* m_nctk/nctk_get_dim
    1870                 :             : !! NAME
    1871                 :             : !!  nctk_get_dim
    1872                 :             : !!
    1873                 :             : !! FUNCTION
    1874                 :             : !!  Get the value of a dimension from its name.
    1875                 :             : !!
    1876                 :             : !! INPUTS
    1877                 :             : !!  ncid=Netcdf identifier.
    1878                 :             : !!  dimname=Name of the dimension.
    1879                 :             : !!  [datamode]=If True, the nc file is set in data mode (default=False)
    1880                 :             : !!
    1881                 :             : !! OUTPUT
    1882                 :             : !!  dimlen=Value of the dimension.
    1883                 :             : !!
    1884                 :             : !! SOURCE
    1885                 :             : 
    1886                 :      311506 : integer function nctk_get_dim(ncid, dimname, dimlen, datamode) result(ncerr)
    1887                 :             : 
    1888                 :             : !Arguments ------------------------------------
    1889                 :             : !scalars
    1890                 :             :  integer,intent(in) :: ncid
    1891                 :             :  character(len=*),intent(in) :: dimname
    1892                 :             :  integer,intent(out) :: dimlen
    1893                 :             :  logical,optional,intent(in) :: datamode
    1894                 :             : 
    1895                 :             : !Local variables-------------------------------
    1896                 :             :  integer :: dimid
    1897                 :             : ! *********************************************************************
    1898                 :             : 
    1899                 :      311506 :  ncerr = nf90_noerr
    1900                 :             : 
    1901         [ +  + ]:      311506 :  if (present(datamode)) then
    1902         [ +  - ]:           2 :    if (datamode) then
    1903         [ -  + ]:           2 :      NCF_CHECK(nctk_set_datamode(ncid))
    1904                 :             :    end if
    1905                 :             :  end if
    1906                 :             : 
    1907                 :      311506 :  ncerr = nf90_inq_dimid(ncid, dimname, dimid)
    1908         [ +  - ]:      311506 :  if (ncerr == nf90_noerr) then
    1909                 :      311506 :    ncerr = nf90_inquire_dimension(ncid, dimid, len=dimlen)
    1910                 :             :  end if
    1911                 :             : 
    1912                 :      311506 : end function nctk_get_dim
    1913                 :             : !!***
    1914                 :             : 
    1915                 :             : !----------------------------------------------------------------------
    1916                 :             : 
    1917                 :             : !!****f* m_nctk/nctk_write_datar
    1918                 :             : !! NAME
    1919                 :             : !! nctk_write_datar
    1920                 :             : !!
    1921                 :             : !! FUNCTION
    1922                 :             : !!  Write an array in real space in netcdf format
    1923                 :             : !!
    1924                 :             : !! INPUTS
    1925                 :             : !!  path=Filename
    1926                 :             : !!  varname=Name of the variable to write.
    1927                 :             : !!  ngfft(18)=information about 3D FFT
    1928                 :             : !!  cplex=1 for real arrays (e.g. GS rhor), 2 for complex array.
    1929                 :             : !!  nfft=number of points in the real space FFT mesh treated by this MPI proc
    1930                 :             : !!  nspden=number of spin-density components
    1931                 :             : !!  comm_fft=MPI communicator (used only if MPI-FFT).
    1932                 :             : !!  fftn3_distrib(n3)=rank of the processors which own fft planes in 3rd dimension.
    1933                 :             : !!  ffti3_local(n3)=local index for 3d dimension
    1934                 :             : !!  datar(cplex*nfft,nspden)= array in real space.
    1935                 :             : !!  [action]
    1936                 :             : !!
    1937                 :             : !! OUTPUT
    1938                 :             : !!  Only writing
    1939                 :             : !!
    1940                 :             : !! SOURCE
    1941                 :             : 
    1942                 :        7680 : integer function nctk_write_datar(varname,path,ngfft,cplex,nfft,nspden,&
    1943                 :        7680 :    comm_fft,fftn3_distrib,ffti3_local,datar,action) result(ncerr)
    1944                 :             : 
    1945                 :             : !Arguments ------------------------------------
    1946                 :             : !scalars
    1947                 :             :  integer,intent(in) :: cplex,nfft,nspden,comm_fft
    1948                 :             :  character(len=*),intent(in) :: path,varname
    1949                 :             :  character(len=*),optional,intent(in) :: action
    1950                 :             : !arrays
    1951                 :             :  integer,intent(in) :: ngfft(18),fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
    1952                 :             :  real(dp),target,intent(in) :: datar(cplex*nfft,nspden)
    1953                 :             : 
    1954                 :             : !Local variables-------------------------------
    1955                 :             : !scalars
    1956                 :             :  integer,parameter :: master=0
    1957                 :             :  integer :: ncid,varid,i3,nproc_fft,me_fft,i3_glob,n1,n2,n3,ispden,cmode
    1958                 :             :  logical :: ionode
    1959                 :             :  character(len=nctk_slen) :: cplex_name,my_action
    1960                 :             :  !character(len=500) :: msg
    1961                 :             : !arrays
    1962                 :        7680 :  real(dp),allocatable :: glob_datar(:,:)
    1963                 :             : ! *************************************************************************
    1964                 :             : 
    1965                 :             :  ! FIXME: Default should be open but this enters into conflict with the abi_estf stuff!
    1966                 :             :  ! if we are using MPI-IO since file is not open with HDF5.
    1967                 :             :  !my_action = "create"; if (present(action)) my_action = action
    1968         [ +  - ]:        7680 :  my_action = "open"; if (present(action)) my_action = action
    1969                 :             : 
    1970                 :        7680 :  nproc_fft = xmpi_comm_size(comm_fft); me_fft = xmpi_comm_rank(comm_fft)
    1971                 :        7680 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
    1972                 :             : 
    1973                 :             :  ! TODO: Be careful here because we should always create with HDF5 if available
    1974                 :             :  ! to avoid problems if we have to reread with nproc_fft > 1 and MPI-IO
    1975                 :        7680 :  ionode = .True.; ncerr = nf90_noerr
    1976         [ +  + ]:        7680 :  if (nproc_fft == 1) then
    1977                 :           0 :    select case(my_action)
    1978                 :             :    case ("open")
    1979                 :           0 :      ncerr = nf90_open(path, mode=nf90_write, ncid=ncid)
    1980                 :             :    case ("create")
    1981                 :        7420 :      ncerr = nctk_open_create(ncid, path, comm_fft)
    1982                 :             :    case default
    1983      [ -  +  - ]:        7420 :      ABI_ERROR(sjoin("Wrong action: ", my_action))
    1984                 :             :    end select
    1985                 :             : 
    1986                 :             :  else
    1987         [ +  - ]:         260 :    if (nctk_has_mpiio) then
    1988                 :         260 :      call wrtout(std_out, strcat("nctk_write_datar: using MPI-IO to write ", varname, path), "COLL")
    1989                 :             : 
    1990                 :         260 :      ncerr = nf90_einval
    1991                 :             : #ifdef HAVE_NETCDF_MPI
    1992                 :           0 :      select case(my_action)
    1993                 :             :      case ("open")
    1994                 :           0 :        ncerr = nf90_open(path, mode=nf90_write, comm=comm_fft, info=xmpio_info, ncid=ncid)
    1995                 :             :      case ("create")
    1996                 :             :        ncerr = nf90_create(path, cmode=ior(ior(nf90_netcdf4, nf90_mpiio), nf90_write), &
    1997                 :         260 :          comm=comm_fft, info=xmpio_info, ncid=ncid)
    1998                 :             :      case default
    1999      [ -  +  - ]:         260 :        ABI_ERROR(strcat("Wrong action:", my_action))
    2000                 :             :      end select
    2001                 :             : #endif
    2002                 :             :    else
    2003                 :             :      ! MPI-FFT without MPI-support. Only master performs IO
    2004                 :           0 :      ionode = (me_fft == master)
    2005         [ #  # ]:           0 :      if (ionode) then
    2006                 :           0 :        select case(my_action)
    2007                 :             :        case ("open")
    2008                 :           0 :          ncerr = nf90_open(path, mode=nf90_write, ncid=ncid)
    2009                 :             :        case ("create")
    2010                 :             :          !ncerr = nf90_create(path, cmode=nf90_clobber, ncid=ncid)
    2011                 :           0 :          cmode = def_cmode_for_seq_create
    2012                 :           0 :          ncerr = nf90_create(path, cmode=cmode, ncid=ncid)
    2013                 :             :        case default
    2014      [ #  #  # ]:           0 :          ABI_ERROR(strcat("Wrong action:", my_action))
    2015                 :             :        end select
    2016                 :             :      end if
    2017                 :             :    end if
    2018                 :             :  end if
    2019         [ -  + ]:        7680 :  NCF_CHECK_MSG(ncerr, sjoin("opening file:", path))
    2020                 :             : 
    2021         [ +  - ]:        7680 :  if (ionode) then
    2022                 :             :    ! Define dims and variables
    2023                 :             :    !write(std_out,*)"defing dims",trim(varname)," in file: ",path
    2024         [ +  - ]:        7680 :    cplex_name = strcat("real_or_complex_", varname)
    2025                 :             :    ncerr = nctk_def_dims(ncid, [&
    2026                 :             :      nctkdim_t(cplex_name, cplex),&
    2027                 :             :      nctkdim_t("number_of_grid_points_vector1", n1),&
    2028                 :             :      nctkdim_t("number_of_grid_points_vector2", n2),&
    2029                 :             :      nctkdim_t("number_of_grid_points_vector3", n3),&
    2030         [ +  + ]:       46080 :      nctkdim_t("number_of_components", nspden)], defmode=.True.)
    2031         [ -  + ]:        7680 :    NCF_CHECK(ncerr)
    2032                 :             : 
    2033                 :             :    ncerr = nctk_def_one_array(ncid, nctkarr_t(name=varname, dtype="dp", shape_str=strcat(cplex_name, &
    2034                 :             : ", number_of_grid_points_vector1, number_of_grid_points_vector2, number_of_grid_points_vector3, number_of_components")),&
    2035   [ +  +  +  - ]:        7680 :    varid=varid)
    2036                 :             : 
    2037                 :             :    ! Add attributes
    2038                 :        7680 :    varid = nctk_idname(ncid, varname)
    2039         [ -  + ]:        7680 :    NCF_CHECK(nf90_put_att(ncid, varid, "units", "atomic units"))
    2040         [ -  + ]:        7680 :    NCF_CHECK(nf90_put_att(ncid, varid, "scale_to_atomic_units", one))
    2041                 :             :  end if
    2042                 :             : 
    2043         [ +  + ]:        7680 :  if (nproc_fft == 1) then
    2044                 :             :    ! no MPI-FFT --> write data directly.
    2045                 :        7420 :    varid = nctk_idname(ncid, varname)
    2046         [ -  + ]:        7420 :    NCF_CHECK(nctk_set_datamode(ncid))
    2047   [ +  +  -  +  :       44520 :    NCF_CHECK(nf90_put_var(ncid, varid, datar, start=[1,1,1,1,1], count=[cplex, n1, n2, n3, nspden]))
                   -  - ]
    2048         [ -  + ]:        7420 :    NCF_CHECK(nf90_close(ncid))
    2049                 :             : 
    2050                 :             :  else
    2051                 :             :    ! Must handle data distribution.
    2052         [ -  + ]:         260 :    ABI_CHECK(mod(n3, nproc_fft) == 0, "assuming mod(n3, nproc_fft) == 0")
    2053                 :             : 
    2054                 :         260 :    i3_glob = -1
    2055         [ +  - ]:        2866 :    do i3=1,ngfft(3)
    2056         [ +  + ]:        2866 :      if (fftn3_distrib(i3) == me_fft) then
    2057                 :             :         i3_glob = i3
    2058                 :             :         exit
    2059                 :             :      end if
    2060                 :             :    end do
    2061         [ -  + ]:         260 :    ABI_CHECK(i3_glob > 0, "negative i3_glob")
    2062                 :             : 
    2063                 :             :    !do i3=i3_glob,ngfft(3)
    2064                 :             :    !  if (fftn3_distrib(i3) /= me_fft) exit
    2065                 :             :    !  !assert all(ffn3_distrib(i3_glob:i3_glob -1 + ngfft(3) / nproc_fft) == me_fft)
    2066                 :             :    !end do
    2067                 :             :    !i3_glob = i3- 1
    2068                 :             :    !print*,"i3_glob",i3_glob
    2069                 :             : 
    2070         [ +  - ]:         260 :    if (ionode) then
    2071         [ -  + ]:         260 :      NCF_CHECK(nf90_enddef(ncid))
    2072                 :             :    end if
    2073                 :             : 
    2074                 :             :    ! Array on disk has shape [cplex, n1, n2, n3, nspden]
    2075         [ +  - ]:         260 :    if (nctk_has_mpiio) then
    2076                 :             :      ! Use collective IO.
    2077                 :         260 :      ncerr = nf90_einval
    2078         [ -  + ]:         260 :      NCF_CHECK(nctk_set_collective(ncid, varid))
    2079                 :             : 
    2080         [ +  + ]:         522 :      do ispden=1,nspden
    2081                 :             :        ncerr = nf90_put_var(ncid, varid, datar(:,ispden), start=[1,1,1,i3_glob,ispden], &
    2082   [ +  +  +  + ]:        2882 :                 count=[cplex,n1,n2,n3/nproc_fft,1])
    2083         [ -  + ]:         522 :        NCF_CHECK(ncerr)
    2084                 :             :      end do
    2085                 :             :    else
    2086                 :             :      ! MPI-FFT without MPI-IO. Collect data (requires more memory and communication)
    2087   [ #  #  #  #  :           0 :      ABI_MALLOC(glob_datar, (cplex*product(ngfft(1:3)), nspden))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    2088                 :           0 :      call collect_datar(ngfft,cplex,nfft,nspden,datar,comm_fft,fftn3_distrib,ffti3_local,glob_datar,master=master)
    2089                 :             : 
    2090         [ #  # ]:           0 :      if (ionode) then
    2091                 :             :        ! Write global array.
    2092   [ #  #  #  #  :           0 :        NCF_CHECK(nf90_put_var(ncid, varid, glob_datar, start=[1,1,1,1,1], count=[cplex,n1,n2,n3,nspden]))
                   #  # ]
    2093                 :             :      end if
    2094         [ #  # ]:           0 :      ABI_FREE(glob_datar)
    2095                 :             :    end if
    2096                 :             : 
    2097         [ +  - ]:         260 :    if (ionode) then
    2098         [ -  + ]:         260 :      NCF_CHECK(nf90_close(ncid))
    2099                 :             :    end if
    2100                 :             :  end if
    2101                 :             : 
    2102                 :             :  !ok = .True.
    2103                 :             :  ! Sequential IO
    2104                 :             :  !do rank=0,nproc_fft-1
    2105                 :             :  !  if (rank == me_fft) then
    2106                 :             :  !     ncerr = nf90_open(path, mode=nf90_write, ncid=ncid)
    2107                 :             :  !     do ispden=1,nspden
    2108                 :             :  !       ncerr = nf90_put_var(ncid, varid, datar(1:,ispden), start=[1,1,1,i3_glob,ispden], &
    2109                 :             :  !                count=[cplex,ngfft(1),ngfft(2),ngfft(3)/nproc_fft,1])
    2110                 :             :  !     end do
    2111                 :             :  !     ncerr = nf90_close(ncid)
    2112                 :             :  !  end if
    2113                 :             :  !  call xmpi_barrier(comm_fft)
    2114                 :             :  !end do
    2115                 :             : 
    2116   [ +  -  -  + ]:       15360 : end function nctk_write_datar
    2117                 :             : !!***
    2118                 :             : 
    2119                 :             : !!****f* m_nctk/nctk_read_datar
    2120                 :             : !! NAME
    2121                 :             : !! nctk_read_datar
    2122                 :             : !!
    2123                 :             : !! FUNCTION
    2124                 :             : !!  Read an array in real space in netcdf format
    2125                 :             : !!
    2126                 :             : !! INPUTS
    2127                 :             : !!  path=Filename
    2128                 :             : !!  varname=Name of the variable to read.
    2129                 :             : !!  ngfft(18)=information about 3D FFT
    2130                 :             : !!  cplex=1 for real arrays (e.g. GS rhor), 2 for complex array.
    2131                 :             : !!  nfft=number of points in the real space FFT mesh treated by this MPI proc
    2132                 :             : !!  nspden=number of spin-density components
    2133                 :             : !!  comm_fft=MPI communicator (used only if MPI-FFT).
    2134                 :             : !!  fftn3_distrib(n3)=rank of the processors which own fft planes in 3rd dimension.
    2135                 :             : !!  ffti3_local(n3)=local index for 3d dimension
    2136                 :             : !!  datar(cplex*nfft,nspden)= array in real space.
    2137                 :             : !!
    2138                 :             : !! OUTPUT
    2139                 :             : !!  Only writing
    2140                 :             : !!
    2141                 :             : !! SOURCE
    2142                 :             : 
    2143                 :           0 : integer function nctk_read_datar(path,varname,ngfft,cplex,nfft,nspden,&
    2144                 :           0 :    comm_fft,fftn3_distrib,ffti3_local,datar) result(ncerr)
    2145                 :             : 
    2146                 :             : !Arguments ------------------------------------
    2147                 :             : !scalars
    2148                 :             :  integer,intent(in) :: cplex,nfft,nspden,comm_fft
    2149                 :             :  character(len=*),intent(in) :: path,varname
    2150                 :             : !arrays
    2151                 :             :  integer,intent(in) :: ngfft(18),fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
    2152                 :             :  real(dp),intent(out) :: datar(cplex*nfft,nspden)
    2153                 :             : 
    2154                 :             : !Local variables-------------------------------
    2155                 :             : !scalars
    2156                 :             :  integer,parameter :: master=0
    2157                 :             :  integer :: ncid,varid,i3,nproc_fft,me_fft,i3_glob,n1,n2,n3,ispden
    2158                 :             :  logical :: ionode
    2159                 :             : !arrays
    2160                 :           0 :  real(dp),allocatable :: glob_datar(:,:)
    2161                 :             : ! *************************************************************************
    2162                 :             : 
    2163                 :           0 :  nproc_fft = xmpi_comm_size(comm_fft); me_fft = xmpi_comm_rank(comm_fft)
    2164                 :           0 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
    2165                 :             : 
    2166                 :             :  ! TODO: Be careful here because we should always create with HDF5 if available
    2167                 :             :  ! to avoid problems if we have to reread with nproc_fft > 1 and MPI-IO
    2168                 :           0 :  ionode = .True.
    2169         [ #  # ]:           0 :  if (nproc_fft == 1) then
    2170                 :           0 :    ncerr = nf90_open(path, mode=nf90_nowrite, ncid=ncid)
    2171                 :             :  else
    2172         [ #  # ]:           0 :    if (nctk_has_mpiio) then
    2173                 :             :      !write(std_out,*)"open_par: ",trim(path)
    2174                 :             :      !ncerr = nf90_open_par(path, nf90_nowrite,
    2175                 :             :      ! Don't know why but the format is not autodected!
    2176                 :             :      ncerr = nf90_einval
    2177                 :             : #ifdef HAVE_NETCDF_MPI
    2178                 :             :      ncerr = nf90_open(path, mode=ior(ior(nf90_netcdf4, nf90_mpiio), nf90_nowrite),&
    2179                 :           0 :                        comm=comm_fft, info=xmpio_info, ncid=ncid)
    2180                 :             : #endif
    2181                 :             :    else
    2182                 :             :      ! MPI-FFT without MPI-support. Only master does IO
    2183                 :           0 :      ionode = (me_fft == master); ncerr = nf90_noerr
    2184         [ #  # ]:           0 :      if (ionode) ncerr = nf90_open(path, nf90_nowrite, ncid)
    2185                 :             :    end if
    2186                 :             :  end if
    2187         [ #  # ]:           0 :  NCF_CHECK_MSG(ncerr, sjoin("opening file: ",path))
    2188                 :             : 
    2189         [ #  # ]:           0 :  NCF_CHECK(nf90_inq_varid(ncid, varname, varid))
    2190                 :             :  !write(std_out,*)"about to read varname, ngfft, cplex, nfft, nspden:", trim(varname), ngfft(:3), cplex,nfft,nspden
    2191                 :             : 
    2192                 :             :  ! netcdf array has shape [cplex, n1, n2, n3, nspden]
    2193         [ #  # ]:           0 :  if (nproc_fft == 1) then
    2194                 :             :    ! No MPI-FFT --> easy
    2195   [ #  #  #  #  :           0 :    NCF_CHECK(nf90_get_var(ncid, varid, datar, start=[1,1,1,1], count=[cplex, n1, n2, n3, nspden]))
                   #  # ]
    2196         [ #  # ]:           0 :    NCF_CHECK(nf90_close(ncid))
    2197                 :             : 
    2198                 :             :  else
    2199                 :             :    ! Handle data distribution.
    2200         [ #  # ]:           0 :    ABI_CHECK(mod(ngfft(3), nproc_fft) == 0, "assuming mod(n3, nproc_fft) == 0")
    2201                 :             : 
    2202                 :           0 :    i3_glob = -1
    2203         [ #  # ]:           0 :    do i3=1,ngfft(3)
    2204         [ #  # ]:           0 :      if (fftn3_distrib(i3) == me_fft) then
    2205                 :             :         i3_glob = i3
    2206                 :             :         exit
    2207                 :             :      end if
    2208                 :             :    end do
    2209         [ #  # ]:           0 :    ABI_CHECK(i3_glob > 0, "negative i3_glob")
    2210                 :             : 
    2211         [ #  # ]:           0 :    if (nctk_has_mpiio) then
    2212                 :             :      ! Use parallel IO with collective calls.
    2213                 :           0 :      ncerr = nf90_einval
    2214         [ #  # ]:           0 :      NCF_CHECK(nctk_set_collective(ncid, varid))
    2215                 :             : 
    2216         [ #  # ]:           0 :      do ispden=1,nspden
    2217                 :             :        ncerr = nf90_get_var(ncid, varid, datar(:,ispden), start=[1,1,1,i3_glob,ispden], &
    2218   [ #  #  #  # ]:           0 :                 count=[cplex,ngfft(1),ngfft(2),ngfft(3)/nproc_fft,1])
    2219         [ #  # ]:           0 :        NCF_CHECK(ncerr)
    2220                 :             :      end do
    2221                 :             :    else
    2222                 :             :      ! MPI-FFT without MPI-IO. Master read and broadcast (requires more memory and communication)
    2223   [ #  #  #  #  :           0 :      ABI_MALLOC(glob_datar, (cplex*product(ngfft(1:3)), nspden))
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    2224         [ #  # ]:           0 :      if (ionode) then
    2225   [ #  #  #  #  :           0 :        NCF_CHECK(nf90_get_var(ncid, varid, glob_datar, start=[1,1,1,1,1], count=[cplex,n1,n2,n3,nspden]))
                   #  # ]
    2226                 :             :      end if
    2227                 :             : 
    2228                 :           0 :      call distrib_datar(ngfft,cplex,nfft,nspden,glob_datar,master,comm_fft,fftn3_distrib,ffti3_local,datar)
    2229         [ #  # ]:           0 :      ABI_FREE(glob_datar)
    2230                 :             :    end if
    2231                 :             : 
    2232         [ #  # ]:           0 :    if (ionode) then
    2233         [ #  # ]:           0 :      NCF_CHECK(nf90_close(ncid))
    2234                 :             :    end if
    2235                 :             :  end if
    2236                 :             : 
    2237         [ #  # ]:           0 : end function nctk_read_datar
    2238                 :             : !!***
    2239                 :             : 
    2240                 :             : !!****f* m_nctk/nctk_prepare_mpiio
    2241                 :             : !! NAME
    2242                 :             : !! nctk_mpiio
    2243                 :             : !!
    2244                 :             : !! FUNCTION
    2245                 :             : !! This function appears to be required to prevent deadlocks during I/O operations in single mode.
    2246                 :             : !! Although single mode is the default, on some architectures or compilers, nf90_put_var
    2247                 :             : !! can deadlock if not all processors in the communicator invoke the function.
    2248                 :             : !! This solution was proposed by Hsiao-Yi Tsai.
    2249                 :             : 
    2250                 :          24 : integer function nctk_prepare_mpiio(ncid, varname) result(ncerr)
    2251                 :             : 
    2252                 :             : !Arguments ------------------------------------
    2253                 :             :  integer,intent(in) :: ncid
    2254                 :             :  character(len=*),intent(in) :: varname
    2255                 :             : 
    2256                 :             : !Local variables-------------------------------
    2257                 :             :  integer :: vid
    2258                 :             :  character(len=nctk_slen) :: out_varname
    2259                 :             : ! *************************************************************************
    2260                 :             : 
    2261                 :          24 :  vid = nctk_idname(ncid, varname)
    2262                 :          24 :  ncerr = nf90_inquire_variable(ncid, vid, out_varname)
    2263                 :             : 
    2264                 :          24 : end function nctk_prepare_mpiio
    2265                 :             : !!***
    2266                 :             : 
    2267                 :             : !----------------------------------------------------------------------
    2268                 :             : 
    2269                 :             : !!****f* m_nctk/collect_datar
    2270                 :             : !! NAME
    2271                 :             : !!  collect_datar
    2272                 :             : !!
    2273                 :             : !! FUNCTION
    2274                 :             : !! Collect a real-space MPI-FFT distributed array on each proc.
    2275                 :             : !!
    2276                 :             : !! INPUTS
    2277                 :             : !!  ngfft(18)=contain all needed information about 3D FFT (see NOTES at beginning of scfcv)
    2278                 :             : !!  cplex=1 if real array, 2 for complex
    2279                 :             : !!  nfft=Number of FFT points treated by this MPI proc
    2280                 :             : !!  nspden=Second dimension of rhor
    2281                 :             : !!  rhor(cplex*nfft,nspden)=Array in real space (MPI-FFT distributed)
    2282                 :             : !!  fftn3_distrib(n3)=rank of the processors which own fft planes in 3rd dimension.
    2283                 :             : !!  fftn3_local(n3)=local i3 indices
    2284                 :             : !!  comm_fft=MPI-FFT communicator
    2285                 :             : !!  [master]=MPI rank, Optional. If present, the global array is available only on master node.
    2286                 :             : !!
    2287                 :             : !! OUTPUT
    2288                 :             : !!   rhor_glob(cplex*nfft_tot,nspden)=Global array
    2289                 :             : !!
    2290                 :             : !! SOURCE
    2291                 :             : 
    2292         [ #  # ]:           0 : subroutine collect_datar(ngfft,cplex,nfft,nspden,rhor,comm_fft,fftn3_distrib,ffti3_local,rhor_glob,master)
    2293                 :             : 
    2294                 :             : !Arguments ------------------------------------
    2295                 :             : !scalars
    2296                 :             :  integer,intent(in) :: cplex,nfft,nspden,comm_fft
    2297                 :             :  integer,optional,intent(in) :: master
    2298                 :             : !arrays
    2299                 :             :  integer,intent(in) :: ngfft(18)
    2300                 :             :  integer,intent(in) :: fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
    2301                 :             :  real(dp),intent(in) :: rhor(cplex*nfft,nspden)
    2302                 :             :  real(dp),intent(out) :: rhor_glob(cplex*product(ngfft(1:3)),nspden)
    2303                 :             : 
    2304                 :             : !Local variables-------------------------------
    2305                 :             :  integer :: ispden,i1,i2,i3,me_fft,i3_local,my_fftbase,glob_fftbase
    2306                 :             :  integer :: n1,n2,n3,ierr,nfft_tot
    2307                 :             : ! *************************************************************************
    2308                 :             : 
    2309         [ #  # ]:           0 :  nfft_tot = product(ngfft(1:3)); me_fft = xmpi_comm_rank(comm_fft)
    2310                 :           0 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
    2311                 :             : 
    2312         [ #  # ]:           0 :  if (nfft_tot == nfft) then
    2313                 :             :    ! full rhor on each node, just do a copy
    2314   [ #  #  #  # ]:           0 :    rhor_glob = rhor
    2315                 :             :  else
    2316                 :             :    ! if MPI-FFT we have to gather the global array on each node.
    2317   [ #  #  #  # ]:           0 :    rhor_glob = zero
    2318         [ #  # ]:           0 :    do ispden=1,nspden
    2319         [ #  # ]:           0 :      do i3=1,n3
    2320         [ #  # ]:           0 :        if (me_fft == fftn3_distrib(i3)) then
    2321                 :           0 :          i3_local = ffti3_local(i3)
    2322         [ #  # ]:           0 :          do i2=1,n2
    2323                 :           0 :            my_fftbase =   cplex * ( (i2-1)*n1 + (i3_local-1)*n1*n2 )
    2324                 :           0 :            glob_fftbase = cplex * ( (i2-1)*n1 + (i3-1)*n1*n2 )
    2325         [ #  # ]:           0 :            do i1=1,cplex * n1
    2326                 :           0 :              rhor_glob(i1+glob_fftbase,ispden) = rhor(i1+my_fftbase,ispden)
    2327                 :             :            end do
    2328                 :             :          end do
    2329                 :             :        end if
    2330                 :             :      end do
    2331                 :             :    end do
    2332         [ #  # ]:           0 :    if (present(master)) then
    2333                 :           0 :      call xmpi_sum_master(rhor_glob,master,comm_fft,ierr)
    2334                 :             :    else
    2335                 :           0 :      call xmpi_sum(rhor_glob,comm_fft,ierr)
    2336                 :             :    end if
    2337                 :             :  end if
    2338                 :             : 
    2339                 :           0 : end subroutine collect_datar
    2340                 :             : !!***
    2341                 :             : 
    2342                 :             : !----------------------------------------------------------------------
    2343                 :             : 
    2344                 :             : !!****f* m_nctk/distrib_datar
    2345                 :             : !! NAME
    2346                 :             : !!  distrib_datar
    2347                 :             : !!
    2348                 :             : !! FUNCTION
    2349                 :             : !! distribute a real-space MPI-FFT
    2350                 :             : !!
    2351                 :             : !! INPUTS
    2352                 :             : !!  ngfft(18)=contain all needed information about 3D FFT (see NOTES at beginning of scfcv)
    2353                 :             : !!  cplex=1 if real array, 2 for complex
    2354                 :             : !!  nfft=Number of FFT points treated by this MPI proc
    2355                 :             : !!  nspden=Second dimension of rhor
    2356                 :             : !!  rhor_glob(cplex*nfft_tot,nspden)=Global array
    2357                 :             : !!  master=The rank of the node that owns the global array.
    2358                 :             : !!  comm_fft=MPI-FFT communicator
    2359                 :             : !!  fftn3_distrib(n3)=rank of the processors which own fft planes in 3rd dimension.
    2360                 :             : !!  fftn3_local(n3)=local i3 indices
    2361                 :             : !!
    2362                 :             : !! OUTPUT
    2363                 :             : !!  rhor(cplex*nfft,nspden)=Array in real space (MPI-FFT distributed)
    2364                 :             : !!
    2365                 :             : !! SOURCE
    2366                 :             : 
    2367         [ #  # ]:           0 : subroutine distrib_datar(ngfft,cplex,nfft,nspden,rhor_glob,master,comm_fft,fftn3_distrib,ffti3_local,rhor)
    2368                 :             : 
    2369                 :             : !Arguments ------------------------------------
    2370                 :             : !scalars
    2371                 :             :  integer,intent(in) :: cplex,nfft,nspden,comm_fft,master
    2372                 :             : !arrays
    2373                 :             :  integer,intent(in) :: ngfft(18)
    2374                 :             :  integer,intent(in) :: fftn3_distrib(ngfft(3)),ffti3_local(ngfft(3))
    2375                 :             :  real(dp),intent(out) :: rhor(cplex*nfft,nspden)
    2376                 :             :  real(dp),intent(inout) :: rhor_glob(cplex*product(ngfft(1:3)),nspden)
    2377                 :             : 
    2378                 :             : !Local variables-------------------------------
    2379                 :             :  integer :: ispden,i1,i2,i3,me_fft,i3_local,my_fftbase,glob_fftbase
    2380                 :             :  integer :: n1,n2,n3,ierr,nfft_tot
    2381                 :             : ! *************************************************************************
    2382                 :             : 
    2383         [ #  # ]:           0 :  nfft_tot = product(ngfft(1:3)); me_fft = xmpi_comm_rank(comm_fft)
    2384                 :           0 :  n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3)
    2385                 :             : 
    2386         [ #  # ]:           0 :  if (nfft_tot == nfft) then
    2387                 :             :    ! full rhor on each node, just do a copy
    2388   [ #  #  #  # ]:           0 :    rhor = rhor_glob
    2389                 :             :  else
    2390                 :             :    ! if MPI-FFT we have to gather the global array on each node.
    2391                 :           0 :    call xmpi_bcast(rhor_glob,master,comm_fft,ierr)
    2392         [ #  # ]:           0 :    do ispden=1,nspden
    2393         [ #  # ]:           0 :      do i3=1,n3
    2394         [ #  # ]:           0 :        if (me_fft == fftn3_distrib(i3)) then
    2395                 :           0 :          i3_local = ffti3_local(i3)
    2396         [ #  # ]:           0 :          do i2=1,n2
    2397                 :           0 :            my_fftbase =   cplex * ( (i2-1)*n1 + (i3_local-1)*n1*n2 )
    2398                 :           0 :            glob_fftbase = cplex * ( (i2-1)*n1 + (i3-1)*n1*n2 )
    2399         [ #  # ]:           0 :            do i1=1,cplex * n1
    2400                 :           0 :              rhor(i1+my_fftbase,ispden) = rhor_glob(i1+glob_fftbase,ispden)
    2401                 :             :            end do
    2402                 :             :          end do
    2403                 :             :        end if
    2404                 :             :      end do
    2405                 :             :    end do
    2406                 :             :  end if
    2407                 :             : 
    2408                 :           0 : end subroutine distrib_datar
    2409                 :             : !!***
    2410                 :             : 
    2411                 :             : !----------------------------------------------------------------------
    2412                 :             : 
    2413                 :             : !!****f* m_nctk/var_from_id
    2414                 :             : !! NAME
    2415                 :             : !!  var_from_id
    2416                 :             : !!
    2417                 :             : !! FUNCTION
    2418                 :             : !!  Initialize a nctkvar_t object from the variable id
    2419                 :             : !!
    2420                 :             : !! INPUTS
    2421                 :             : !!  ncid=NC file handle
    2422                 :             : !!  varid=Variable ID
    2423                 :             : !!
    2424                 :             : !! OUTPUT
    2425                 :             : !!  var<nctkvar_t>=Info on the variable.
    2426                 :             : !!
    2427                 :             : !! SOURCE
    2428                 :             : 
    2429   [ +  +  +  + ]:   665848200 : subroutine var_from_id(ncid, varid, var)
    2430                 :             : 
    2431                 :             : !Arguments ------------------------------------
    2432                 :             :  integer, intent(in) :: ncid, varid
    2433                 :             :  type(nctkvar_t), intent(out) :: var
    2434                 :             : 
    2435                 :             : !Local variables-------------------------------
    2436                 :             : !scalars
    2437                 :             :  integer :: ii, ncerr
    2438                 :             :  !character(len=NF90_MAX_NAME) :: ncname
    2439                 :             : ! *********************************************************************
    2440                 :             : 
    2441                 :             :  ! Get info about the variable.
    2442                 :      324804 :  var%id = varid
    2443                 :             :  ncerr = nf90_inquire_variable(ncid, var%id, &
    2444                 :      324804 :    name=var%name, xtype=var%xtype, ndims=var%ndims, dimids=var%dimids, natts=var%natts)
    2445         [ -  + ]:      324804 :  NCF_CHECK(ncerr)
    2446                 :             : 
    2447                 :             :  ! Get info about dimensions.
    2448         [ +  + ]:      324804 :  if (var%ndims > 0) then
    2449         [ +  + ]:      641771 :    do ii=1,var%ndims
    2450                 :      416005 :      ncerr = nf90_inquire_dimension(ncid, var%dimids(ii), len=var%dimlens(ii), name=var%dimnames(ii))
    2451         [ -  + ]:      641771 :      NCF_CHECK(ncerr)
    2452                 :             :    end do
    2453                 :             :  end if
    2454                 :             : 
    2455                 :             :  ! Get the number of attributes and their names.
    2456                 :             :  !if (var%natts > 0) then
    2457                 :             :  !   do ii=1,var%natts
    2458                 :             :  !      ncerr = nf90_inq_attname(ncid, var%id, ii, var%attnames(ii))
    2459                 :             :  !   end do
    2460                 :             :  !end if
    2461                 :             : 
    2462                 :      324804 : end subroutine var_from_id
    2463                 :             : !!***
    2464                 :             : 
    2465                 :             : !----------------------------------------------------------------------
    2466                 :             : 
    2467                 :             : !!****f* m_nctk/var_from_name
    2468                 :             : !! NAME
    2469                 :             : !!  var_from_name
    2470                 :             : !!
    2471                 :             : !! FUNCTION
    2472                 :             : !!  Initialize a nctkvar_t object from the variable name
    2473                 :             : !!
    2474                 :             : !! INPUTS
    2475                 :             : !!  ncid=NC file handle
    2476                 :             : !!  name=Variable name
    2477                 :             : !!
    2478                 :             : !! OUTPUT
    2479                 :             : !!  var<nctkvar_t>=Info on the variable.
    2480                 :             : !!
    2481                 :             : !! SOURCE
    2482                 :             : 
    2483                 :             : subroutine var_from_name(ncid, name, var)
    2484                 :             : 
    2485                 :             : !Arguments ------------------------------------
    2486                 :             :  integer, intent(in) :: ncid
    2487                 :             :  character(len=*),intent(in) :: name
    2488                 :             :  type(nctkvar_t), intent(out) :: var
    2489                 :             : 
    2490                 :             : !Local variables-------------------------------
    2491                 :             : !scalars
    2492                 :             :  integer :: varid
    2493                 :             : ! *********************************************************************
    2494                 :             : 
    2495                 :             :  varid = nctk_idname(ncid, name)
    2496                 :             :  call var_from_id(ncid, varid, var)
    2497                 :             : 
    2498                 :             : end subroutine var_from_name
    2499                 :             : !!***
    2500                 :             : 
    2501                 :             : !!****f* m_nctk/create_nc_file
    2502                 :             : !! NAME
    2503                 :             : !! create_nc_file
    2504                 :             : !!
    2505                 :             : !! FUNCTION
    2506                 :             : !! Create an NetCDF file including a dimension one definition
    2507                 :             : !!
    2508                 :             : !! INPUTS
    2509                 :             : !!
    2510                 :             : !! OUTPUT
    2511                 :             : !!
    2512                 :             : !! TODO:
    2513                 :             : !!  Remove
    2514                 :             : !!
    2515                 :             : !! SOURCE
    2516                 :             : 
    2517                 :        4166 : subroutine create_nc_file(filename, ncid)
    2518                 :             : 
    2519                 :             : !Arguments ------------------------------------
    2520                 :             : !scalars
    2521                 :             :  integer,intent(out) :: ncid
    2522                 :             : !arrays
    2523                 :             : character(len=*),intent(in) :: filename
    2524                 :             : 
    2525                 :             : !Local variables-------------------------------
    2526                 :             : integer :: one_id, ncerr, cmode
    2527                 :             : ! *************************************************************************
    2528                 :             : 
    2529                 :             :  ncid = 0
    2530                 :             :  ! Create the NetCDF file
    2531                 :             :  !ncerr = nf90_create(path=filename,cmode=NF90_CLOBBER,ncid=ncid)
    2532                 :        4166 :  cmode = def_cmode_for_seq_create
    2533                 :        4166 :  ncerr = nf90_create(path=filename, cmode=cmode, ncid=ncid)
    2534         [ -  + ]:        4166 :  NCF_CHECK_MSG(ncerr, sjoin('Error while creating:', filename))
    2535                 :        4166 :  ncerr=nf90_def_dim(ncid,'one',1,one_id)
    2536         [ -  + ]:        4166 :  NCF_CHECK_MSG(ncerr,'nf90_def_dim')
    2537                 :             : 
    2538                 :        4166 :  end subroutine create_nc_file
    2539                 :             : !!***
    2540                 :             : 
    2541                 :             : !!****f* m_nctk/write_var_netcdf
    2542                 :             : !!
    2543                 :             : !! NAME
    2544                 :             : !! write_var_netcdf
    2545                 :             : !!
    2546                 :             : !! FUNCTION
    2547                 :             : !! Write variable into a netcdf dataset
    2548                 :             : !!
    2549                 :             : !! TODO:
    2550                 :             : !!  Remove!
    2551                 :             : !!
    2552                 :             : !! INPUTS
    2553                 :             : !! arr_int
    2554                 :             : !! arr_real
    2555                 :             : !! marr
    2556                 :             : !! narr
    2557                 :             : !! typevar
    2558                 :             : !! varname
    2559                 :             : !!
    2560                 :             : !! OUTPUT
    2561                 :             : !!  (only writing)
    2562                 :             : !!
    2563                 :             : !! SOURCE
    2564                 :             : 
    2565                 :      422144 : subroutine write_var_netcdf(arr_int,arr_real,marr,narr,ncid,typevar,varname)
    2566                 :             : 
    2567                 :             : !Arguments ------------------------------------
    2568                 :             : !scalars
    2569                 :             :  integer,intent(in) :: narr,marr,ncid
    2570                 :             :  character(len=*),intent(in) :: varname
    2571                 :             :  character(len=3),intent(in) :: typevar
    2572                 :             : !arrays
    2573                 :             :  integer,intent(in) :: arr_int(marr)
    2574                 :             :  real(dp),intent(in) :: arr_real(marr)
    2575                 :             : 
    2576                 :             : !Local variables-------------------------------
    2577                 :             : !scalars
    2578                 :             :  integer :: var_id,var_type,vardim_id,ncerr
    2579                 :             :  !character(len=500) :: msg
    2580                 :             : ! *************************************************************************
    2581                 :             : 
    2582                 :             :  !write(std_out,*)"about to write varname: ",trim(varname)
    2583                 :             : 
    2584         [ +  + ]:      422144 :  if (ncid>0) then
    2585                 :             : !  ### Put the file in definition mode
    2586                 :      291056 :    ncerr=nf90_redef(ncid)
    2587         [ -  + ]:      291056 :    if (ncerr/=NF90_NOERR.and.ncerr/=NF90_EINDEFINE) then
    2588                 :           0 :      NCF_CHECK_MSG(ncerr,'nf90_redef')
    2589                 :             :    end if
    2590                 :             : !  ### Define the dimensions
    2591         [ +  + ]:      291056 :    if (narr==1)then
    2592                 :      207110 :      ncerr=nf90_inq_dimid(ncid,'one',vardim_id)
    2593         [ -  + ]:      207110 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    2594                 :             :    else
    2595                 :       83946 :      ncerr=nf90_def_dim(ncid,trim(varname),narr,vardim_id)
    2596         [ -  + ]:       83946 :      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
    2597                 :             :    end if
    2598                 :             : !  ### Define the variables
    2599         [ +  + ]:      291056 :    if (typevar=='INT') then
    2600                 :      177118 :      var_type=NF90_INT
    2601         [ +  - ]:      113938 :    else if (typevar=='DPR') then
    2602                 :      113938 :      var_type=NF90_DOUBLE
    2603                 :             :    end if
    2604                 :      291056 :    ncerr=nf90_def_var(ncid, trim(varname), var_type, vardim_id, var_id)
    2605         [ -  + ]:      291056 :    NCF_CHECK_MSG(ncerr,'nf90_def_var')
    2606                 :             : !  ### Put the file in data mode
    2607                 :      291056 :    ncerr=nf90_enddef(ncid)
    2608         [ -  + ]:      291056 :    if (ncerr/=NF90_NOERR.and.ncerr/=NF90_ENOTINDEFINE) then
    2609                 :           0 :      NCF_CHECK_MSG(ncerr,'nf90_enddef')
    2610                 :             :    end if
    2611                 :             : !  ### Write variables into the dataset
    2612         [ +  + ]:      291056 :    if (typevar=='INT') then
    2613         [ +  + ]:      354236 :      ncerr=nf90_put_var(ncid,var_id,arr_int,start=(/1/),count=(/narr/))
    2614         [ +  - ]:      113938 :    else if (typevar=='DPR') then
    2615         [ +  + ]:      227876 :      ncerr=nf90_put_var(ncid,var_id,arr_real,start=(/1/),count=(/narr/))
    2616                 :             :    end if
    2617         [ -  + ]:      291056 :    NCF_CHECK_MSG(ncerr,'nf90_put_var')
    2618                 :             :  end if
    2619                 :             : 
    2620                 :      422144 : end subroutine write_var_netcdf
    2621                 :             : !!***
    2622                 :             : 
    2623                 :             : !!****f* ABINIT/write_eig
    2624                 :             : !!
    2625                 :             : !! NAME
    2626                 :             : !! write_eig
    2627                 :             : !!
    2628                 :             : !! FUNCTION
    2629                 :             : !! Write the eigenvalues band by band and k point by k point
    2630                 :             : !! in a NetCDF file format
    2631                 :             : !!
    2632                 :             : !! INPUTS
    2633                 :             : !! filname = Filename of the file where the history will be stored
    2634                 :             : !!
    2635                 :             : !! OUTPUT
    2636                 :             : !!  (only writing)
    2637                 :             : !!
    2638                 :             : !! SOURCE
    2639                 :             : 
    2640                 :        2695 : subroutine write_eig(eigen,fermie,filename,kptns,mband,nband,nkpt,nsppol,&
    2641                 :             : & extfpmd_eshift) ! Optional arguments
    2642                 :             : 
    2643                 :             : !Arguments ------------------------------------
    2644                 :             : !scalars
    2645                 :             :  character(len=fnlen),intent(in) :: filename
    2646                 :             :  integer,intent(in) :: nkpt,nsppol,mband
    2647                 :             :  real(dp),intent(in) :: fermie
    2648                 :             :  real(dp),optional,intent(in) :: extfpmd_eshift
    2649                 :             : !arrays
    2650                 :             :  integer,intent(in) :: nband(nkpt*nsppol)
    2651                 :             :  real(dp),intent(in) :: eigen(mband*nkpt*nsppol)
    2652                 :             :  real(dp),intent(in) :: kptns(3,nkpt)
    2653                 :             : 
    2654                 :             : !Local variables-------------------------------
    2655                 :             : !scalars
    2656                 :             :  integer :: ncerr,ncid,ii, cmode
    2657                 :             :  integer :: xyz_id,nkpt_id,mband_id,nsppol_id
    2658                 :             :  integer :: eig_id,fermie_id,kpt_id,nbk_id,nbk
    2659                 :             :  integer :: extfpmd_eshift_id
    2660                 :             :  integer :: ikpt,isppol,nband_k,band_index
    2661                 :             :  real(dp):: convrt
    2662                 :             : !arrays
    2663                 :             :  integer :: dimEIG(3),dimKPT(2),dimNBK(2)
    2664                 :             :  integer :: count2(2),start2(2)
    2665                 :             :  integer :: count3(3),start3(3)
    2666                 :             :  integer :: dim0(0)
    2667                 :        5390 :  real(dp):: band(mband)
    2668                 :             : ! *********************************************************************
    2669                 :             : 
    2670                 :        2695 :  convrt=1.0_dp
    2671                 :             : 
    2672                 :             : !1. Create netCDF file
    2673                 :             :  !ncerr = nf90_create(path=trim(filename),cmode=NF90_CLOBBER, ncid=ncid)
    2674                 :        2695 :  cmode = def_cmode_for_seq_create
    2675                 :        2695 :  ncerr = nf90_create(path=trim(filename), cmode=cmode, ncid=ncid)
    2676         [ -  + ]:        2695 :  NCF_CHECK_MSG(ncerr," create netcdf EIG file")
    2677                 :             : 
    2678                 :             : !2. Define dimensions
    2679                 :        2695 :  ncerr = nf90_def_dim(ncid,"xyz",3,xyz_id)
    2680         [ -  + ]:        2695 :  NCF_CHECK_MSG(ncerr," define dimension xyz")
    2681                 :             : 
    2682                 :        2695 :  ncerr = nf90_def_dim(ncid,"mband",mband,mband_id)
    2683         [ -  + ]:        2695 :  NCF_CHECK_MSG(ncerr," define dimension mband")
    2684                 :             : 
    2685                 :        2695 :  ncerr = nf90_def_dim(ncid,"nkpt",nkpt,nkpt_id)
    2686         [ -  + ]:        2695 :  NCF_CHECK_MSG(ncerr," define dimension nkpt")
    2687                 :             : 
    2688                 :        2695 :  ncerr = nf90_def_dim(ncid,"nsppol",nsppol,nsppol_id)
    2689         [ -  + ]:        2695 :  NCF_CHECK_MSG(ncerr," define dimension nsppol")
    2690                 :             : 
    2691                 :             : !Dimensions for EIGENVALUES
    2692         [ +  + ]:       10780 :  dimEIG = (/ mband_id, nkpt_id, nsppol_id /)
    2693                 :             : !Dimensions for kpoint positions
    2694         [ +  + ]:        8085 :  dimKPT = (/ xyz_id, nkpt_id /)
    2695                 :             : !Dimensions for number kpoints per band and spin
    2696                 :             : !dimNBK = (/ nkpt_id, nsppol_id /)
    2697         [ +  + ]:        8085 :  dimNBK = (/ nkpt_id, nsppol_id /)
    2698                 :             : 
    2699                 :             : !3. Define variables
    2700                 :             :  call ab_define_var(ncid,dim0,fermie_id,NF90_DOUBLE,&
    2701                 :        2695 : & "fermie","Chemical potential","Hartree")
    2702                 :             :  call ab_define_var(ncid, dimEIG, eig_id, NF90_DOUBLE,&
    2703                 :             : & "Eigenvalues",&
    2704                 :             : & "Values of eigenvalues",&
    2705                 :        2695 : & "Hartree")
    2706                 :             :  call ab_define_var(ncid, dimKPT, kpt_id, NF90_DOUBLE,"Kptns",&
    2707                 :             : & "Positions of K-points in reciprocal space",&
    2708                 :        2695 : & "Dimensionless")
    2709                 :             :  call ab_define_var(ncid, dimNBK, nbk_id, NF90_INT,"NBandK",&
    2710                 :             : & "Number of bands per kpoint and Spin",&
    2711                 :        2695 : & "Dimensionless")
    2712         [ -  + ]:        2695 :  if(present(extfpmd_eshift)) then
    2713                 :             :     call ab_define_var(ncid,dim0,extfpmd_eshift_id,NF90_DOUBLE,&
    2714                 :           0 : &    "extfpmd_eshift","Extended FPMD energy shift","Hartree")
    2715                 :             :  end if
    2716                 :             : 
    2717                 :             : !4. End define mode
    2718                 :        2695 :  ncerr = nf90_enddef(ncid)
    2719         [ -  + ]:        2695 :  NCF_CHECK_MSG(ncerr," end define mode")
    2720                 :             : 
    2721                 :             : !5 Write kpoint positions
    2722         [ +  + ]:       30649 :  do ikpt=1,nkpt
    2723         [ +  + ]:       83862 :    start2 = (/ 1, ikpt /)
    2724                 :       27954 :    count2 = (/ 3, 1 /)
    2725                 :             :    ncerr = nf90_put_var(ncid, kpt_id,&
    2726                 :             : &   kptns(1:3,ikpt),&
    2727                 :             : &   start = start2,&
    2728                 :       27954 : &   count = count2)
    2729         [ -  + ]:       30649 :    NCF_CHECK_MSG(ncerr," write variable kptns")
    2730                 :             :  end do
    2731                 :             : 
    2732                 :             : !6.1 Write chemical potential
    2733                 :        2695 :  ncerr = nf90_put_var(ncid, fermie_id, fermie)
    2734         [ -  + ]:        2695 :  NCF_CHECK_MSG(ncerr," write variable fermie")
    2735                 :             : 
    2736                 :             : !6.2 Write extfpmd shiftfactor
    2737         [ -  + ]:        2695 :  if(present(extfpmd_eshift)) then
    2738                 :           0 :    ncerr = nf90_put_var(ncid, extfpmd_eshift_id, extfpmd_eshift)
    2739         [ #  # ]:           0 :    NCF_CHECK_MSG(ncerr," write variable extfpmd_eshift")
    2740                 :             :  end if
    2741                 :             : 
    2742                 :             : !6.3 Write eigenvalues
    2743                 :             :  band_index=0
    2744         [ +  + ]:        5654 :  do isppol=1,nsppol
    2745         [ +  + ]:       34653 :    do ikpt=1,nkpt
    2746                 :       28999 :      nband_k=nband(ikpt+(isppol-1)*nkpt)
    2747         [ +  + ]:      115996 :      start3 = (/ 1, ikpt, isppol /)
    2748         [ +  + ]:      115996 :      count3 = (/ mband, 1, 1 /)
    2749         [ +  + ]:      291595 :      band(:)=zero
    2750         [ +  + ]:      291519 :      do ii=1,nband_k
    2751                 :      291519 :        band(ii)=eigen(band_index+ii)
    2752                 :             :      end do
    2753                 :             :      ncerr = nf90_put_var(ncid, eig_id,&
    2754                 :             : &     band,&
    2755                 :             : &     start = start3,&
    2756                 :       28999 : &     count = count3)
    2757         [ -  + ]:       28999 :      NCF_CHECK_MSG(ncerr," write variable band")
    2758                 :             : 
    2759                 :       31958 :      band_index=band_index+nband_k
    2760                 :             :    end do
    2761                 :             :  end do
    2762                 :             : 
    2763                 :             : !6.4 Write Number of bands per kpoint and Spin
    2764                 :             : 
    2765         [ +  + ]:        5654 :  do isppol=1,nsppol
    2766         [ +  + ]:       34653 :    do ikpt=1,nkpt
    2767         [ +  + ]:       86997 :      start2 = (/ ikpt, 1 /)
    2768                 :       28999 :      count2 = (/ 1, 1 /)
    2769                 :       28999 :      nbk=nband(ikpt+(isppol-1)*nkpt)
    2770                 :             :      ncerr = nf90_put_var(ncid, nbk_id,&
    2771                 :             : &     nbk,&
    2772                 :       28999 : &     start = start2)
    2773         [ -  + ]:       31958 :      NCF_CHECK_MSG(ncerr," write variable nband")
    2774                 :             :    end do
    2775                 :             :  end do
    2776                 :             : 
    2777                 :             : !7 Close file
    2778                 :             : 
    2779                 :        2695 :  ncerr = nf90_close(ncid)
    2780         [ -  + ]:        2695 :  NCF_CHECK_MSG(ncerr," close netcdf EIG file")
    2781                 :             : 
    2782                 :        2695 : end subroutine write_eig
    2783                 :             : !!***
    2784                 :             : 
    2785                 :           0 : END MODULE m_nctk
    2786                 :             : !!***
        

Generated by: LCOV version 2.3-1