LCOV - code coverage report
Current view: top level - src - mo_io.f90 (source / functions) Hit Total Coverage
Test: forces coverage Lines: 36 53 67.9 %
Date: 2024-03-13 19:03:28 Functions: 3 4 75.0 %

          Line data    Source code
       1             : !> \file    mo_io.f90
       2             : !> \brief \copybrief mo_io
       3             : !> \details \copydetails mo_io
       4             : 
       5             : !> \brief   File reading routines.
       6             : !> \details This module provides routines to load a file into an array.
       7             : !!          This is mainly taken from the Fortran stdlib: https://github.com/fortran-lang/stdlib
       8             : !> \version 0.1
       9             : !> \authors Sebastian Mueller
      10             : !> \date    Apr 2022
      11             : !> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
      12             : !! FORCES is released under the LGPLv3+ license \license_note
      13             : module mo_io
      14             : 
      15             :   use mo_kind, only: i4, dp, sp
      16             :   use mo_message, only: error_message
      17             :   use mo_string_utils, only: is_blank
      18             : 
      19             :   implicit none
      20             :   private
      21             :   public :: loadtxt
      22             :   public :: number_of_columns
      23             :   public :: number_of_rows
      24             : 
      25             :   !> \brief   Read a file into a 2D array containing reals.
      26             :   interface loadtxt
      27             :     module procedure loadtxt_dp, loadtxt_sp
      28             :   end interface loadtxt
      29             : 
      30             : contains
      31             : 
      32             :   !> \brief   Read a file into a 2D array containing reals.
      33           2 :   subroutine loadtxt_dp(filename, d, skiprows, max_rows)
      34             : 
      35             :     !> Filename to load the array from
      36             :     character(len=*), intent(in) :: filename
      37             :     !> The array 'd' will be automatically allocated with the correct dimensions
      38             :     real(dp), allocatable, intent(out) :: d(:,:)
      39             :     !> lines to skip at the begining
      40             :     integer(i4), intent(in), optional :: skiprows
      41             :     !> Read max_rows lines of content after skiprows lines. The default is to read all the lines (negative values).
      42             :     integer(i4), intent(in), optional :: max_rows
      43             : 
      44             :     integer(i4) :: u,  nrow, ncol, i, skiprows_, max_rows_
      45             : 
      46           2 :     skiprows_ = 0
      47           2 :     if ( present(skiprows) ) skiprows_ = max(skiprows, 0)
      48             : 
      49           2 :     max_rows_ = -1
      50           2 :     if ( present(max_rows) ) max_rows_ = max_rows
      51             : 
      52           2 :     open(newunit=u, file=filename, action='read', position='asis', status='old', access='stream', form='formatted')
      53             : 
      54             :     ! determine size
      55           2 :     ncol = number_of_columns(u)
      56           2 :     nrow = number_of_rows(u)
      57           2 :     skiprows_ = min(skiprows_, nrow)
      58           2 :     if ( max_rows_ < 0 .or. max_rows_ > (nrow - skiprows_)) max_rows_ = nrow - skiprows_
      59             : 
      60           8 :     allocate(d(max_rows_, ncol))
      61             : 
      62           6 :     do i = 1, skiprows_
      63           6 :       read(u, *)
      64             :     end do
      65             : 
      66       14602 :     do i = 1, max_rows_
      67       14602 :       read(u, "(*(es24.16e3,1x))") d(i, :)
      68             :     end do
      69             : 
      70           2 :     close(u)
      71             : 
      72           2 :   end subroutine loadtxt_dp
      73             : 
      74             :   !> \brief   Read a file into a 2D array containing reals.
      75           0 :   subroutine loadtxt_sp(filename, d, skiprows, max_rows)
      76             : 
      77             :     !> Filename to load the array from
      78             :     character(len=*), intent(in) :: filename
      79             :     !> The array 'd' will be automatically allocated with the correct dimensions
      80             :     real(sp), allocatable, intent(out) :: d(:,:)
      81             :     !> lines to skip at the begining
      82             :     integer(i4), intent(in), optional :: skiprows
      83             :     !> Read max_rows lines of content after skiprows lines. The default is to read all the lines (negative values).
      84             :     integer(i4), intent(in), optional :: max_rows
      85             : 
      86             :     integer(i4) :: u, nrow, ncol, i, skiprows_, max_rows_
      87             : 
      88           0 :     skiprows_ = 0
      89           0 :     if ( present(skiprows) ) skiprows_ = max(skiprows, 0)
      90             : 
      91           0 :     max_rows_ = -1
      92           0 :     if ( present(max_rows) ) max_rows_ = max_rows
      93             : 
      94           0 :     open(newunit=u, file=filename, action='read', position='asis', status='old', access='stream', form='formatted')
      95             : 
      96             :     ! determine size
      97           0 :     ncol = number_of_columns(u)
      98           0 :     nrow = number_of_rows(u)
      99           0 :     skiprows_ = min(skiprows_, nrow)
     100           0 :     if ( max_rows_ < 0 .or. max_rows_ > (nrow - skiprows_)) max_rows_ = nrow - skiprows_
     101             : 
     102           0 :     allocate(d(max_rows_, ncol))
     103             : 
     104           0 :     do i = 1, skiprows_
     105           0 :       read(u, *)
     106             :     end do
     107             : 
     108           0 :     do i = 1, max_rows_
     109           0 :       read(u, "(*(es15.8e2,1x))") d(i, :)
     110             :     end do
     111             : 
     112           0 :     close(u)
     113             : 
     114           2 :   end subroutine loadtxt_sp
     115             : 
     116             :   !> \brief   Determine number of columns in a file. The columns are assumed to be separated by spaces or tabs.
     117             :   !> \return  Number of columns.
     118           2 :   integer function number_of_columns(u)
     119             : 
     120             :     integer(i4),intent(in) :: u !< unit of the open file
     121             :     integer(i4) :: ios
     122             :     character :: c
     123             :     logical :: lastblank
     124             : 
     125           2 :     rewind(u)
     126           2 :     number_of_columns = 0
     127           2 :     lastblank = .true.
     128             :     do
     129          20 :       read(u, '(a)', advance='no', iostat=ios) c
     130          20 :       if (ios /= 0) exit
     131          18 :       if (lastblank .and. .not. is_blank(c)) number_of_columns = number_of_columns + 1
     132           2 :       lastblank = is_blank(c)
     133             :     end do
     134           2 :     rewind(u)
     135             : 
     136           0 :   end function number_of_columns
     137             : 
     138             :   !> \brief   Determine number of rows in a file.
     139             :   !> \return  Number of rows.
     140           2 :   integer function number_of_rows(u)
     141             : 
     142             :     integer(i4), intent(in) :: u !< unit of the open file
     143             :     integer(i4) :: ios
     144             : 
     145           2 :     rewind(u)
     146           2 :     number_of_rows = 0
     147       14604 :     do
     148       14606 :       read(u, *, iostat=ios)
     149       14606 :       if (ios /= 0) exit
     150       14604 :       number_of_rows = number_of_rows + 1
     151             :     end do
     152           2 :     rewind(u)
     153             : 
     154           2 :   end function number_of_rows
     155             : 
     156             : end module mo_io

Generated by: LCOV version 1.16