ParamfileRegions.f90 Source File


Source Code

module ParamfileRegions
   use SMConstants
   use Utilities, only: toLower
   implicit none
!
!  ******************
!  File configuration
!  ******************
!
   private
   public  readValueInRegion , getSquashedLine
   character, parameter       :: comment = '!'
   character, parameter       :: equal(2) = ['=',':'] 
   integer,   parameter       :: STR_LEN_PARAM = 512

   interface readValueInRegion
      module procedure readCharacterValueInRegion , readIntegerValueInRegion , readRealValueInRegion , readLogicalValueInRegion
   end interface readValueInRegion
!
   
!
!  ========
   contains
!  ========
!
!
!/////////////////////////////////////////////////////////////////////////////////////////////////////////////
!
      subroutine readCharacterValueInRegion(fileName , label , var , in_label , out_label)
         implicit none
         character(len=*), intent(in) :: fileName
         character(len=*), intent(in) :: label
         character(len=*)             :: var
         character(len=*), intent(in) :: in_label
         character(len=*), intent(in) :: out_label
!        -------------------------------------------------------------
         integer               :: fID
         character(len=STR_LEN_PARAM)            :: auxstr
         integer               :: io
         integer               :: position
         logical               :: inside
         
         inside = .false.
!
!        Open file
!        ---------
         open ( newunit = fID , file = trim(fileName) , status = 'old' , action = 'read' ) 

         do 
            read( fID , '(A)' , iostat = io ) auxstr
            call toLower(auxstr)
            if (io .lt. 0) then
               var = ""
               exit

            elseif (io .gt. 0) then
               print*, "IOSTAT returned a positive number"
               error stop "Stopped."
         
            else
               
!
!              Check if inside a zone
!              ----------------------
               if ( getSquashedLine(auxstr) .eq. getSquashedLine(in_label) ) then
                  inside = .true.
                  cycle
               elseif( getSquashedLine(auxstr) .eq. getSquashedLine(out_label) ) then
                  inside = .false.
                  cycle
               end if

!              Removed commented part of the string
!              ------------------------------------
               if (inside) then
                  position = index(trim(auxstr) , comment)
                  if ( position .gt. 0 ) then
                     auxstr = auxstr(1:position-1)
                  end if
!   
!                 Look for the label
!                 ------------------
                  position = index(trim(auxstr) , trim(label) )
                  if ( position .eq. 0) then
                     cycle
                  end if
!   
!                 The label is present. Check whether the equal is present
!                 --------------------------------------------------------
                  position = max(index(trim(auxstr) , equal(1)) , index(trim(auxstr) , equal(2)) )
                  if ( position .eq. 0 ) then
                     cycle
                  end if

                  if ( getSquashedLine(auxstr(1:position-1)) .eq. getSquashedLine(label) ) then
!
!                    The label matches the one present in the string
!                    -----------------------------------------------
                     auxstr = auxstr(position+1:)
                  else
                     cycle
                  end if
!   
!                 Get the value
!                 -------------
                  var = trim(adjustl(auxstr))

                  exit
               end if

            end if
         end do

!
!        Close file
!        ----------
         close ( fID ) 
      

      end subroutine readCharacterValueInRegion

      subroutine readIntegerValueInRegion(fileName , label , var , in_label , out_label )
         implicit none
         character(len=*), intent(in) :: fileName
         character(len=*), intent(in) :: label
         integer, allocatable         :: var
         character(len=*), intent(in) :: in_label
         character(len=*), intent(in) :: out_label
         character(len=STR_LEN_PARAM) :: auxstr
         integer                      :: io

         call readCharacterValueInRegion(fileName , label, auxstr , in_label , out_label)

         auxstr = trim(adjustl(auxstr))
         
         if( .not. allocated(var)) allocate(var)
         read(auxstr,*,iostat=io) var
         if (io .lt. 0) then
            deallocate(var)
         end if
 

      end subroutine readIntegerValueInRegion

      subroutine readRealValueInRegion(fileName , label , var , in_label , out_label)
         implicit none
         character(len=*), intent(in) :: fileName
         character(len=*), intent(in) :: label
         real(kind=RP), allocatable   :: var
         character(len=*), intent(in) :: in_label
         character(len=*), intent(in) :: out_label
         character(len=STR_LEN_PARAM) :: auxstr
         integer                      :: io
      
         call readCharacterValueInRegion(fileName , label, auxstr , in_label , out_label)

         auxstr = trim(adjustl(auxstr))
         
         if( .not. allocated(var)) allocate(var)
         read(auxstr,*,iostat=io) var
         if (io .lt. 0) then
            deallocate(var)
         end if
      
      end subroutine readRealValueInRegion

      subroutine readLogicalValueInRegion(fileName , label , var , in_label , out_label)
         implicit none
         character(len=*), intent(in) :: fileName
         character(len=*), intent(in) :: label
         logical, allocatable         :: var
         character(len=*), intent(in) :: in_label
         character(len=*), intent(in) :: out_label
         character(len=STR_LEN_PARAM) :: auxstr
         integer                      :: io
      
         call readCharacterValueInRegion(fileName , label, auxstr , in_label , out_label)

         auxstr = trim(adjustl(auxstr))

         if( .not. allocated(var)) allocate(var)
         read(auxstr,*,iostat=io) var
         if (io .lt. 0) then
            deallocate(var)
         end if

      end subroutine readLogicalValueInRegion

      function getSquashedLine(line) result (squashed)
         implicit none
         character(len=*), intent(in)     :: line
         character(len=STR_LEN_PARAM)     :: squashed
         integer                          :: pos
!
!        First remove comments
!        ---------------------
         pos = index(trim(line) , comment)
         if ( pos .gt. 0 ) then
            squashed = trim(adjustl(line(1:pos-1)))

         else
            squashed = trim(adjustl(line))
         end if

         pos = index(trim(adjustl(squashed)),' ')

         if (pos .eq. 0) then
            squashed = trim(adjustl(squashed))
         else
            squashed = squashed(1:pos-1) // squashed(pos+1:)
         end if

         do
            pos = index(trim(adjustl(squashed)),' ')

            if (pos .eq. 0) then
               squashed = trim(adjustl(squashed))
               return
            else
               squashed = squashed(1:pos-1) // squashed(pos+1:)
            end if
         end do
            
         write(squashed,'(A)')  trim(adjustl(squashed))

      end function getSquashedLine

end module ParamfileRegions