2018-06-10 14:37:17 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH
|
|
|
|
!> @brief Reads in the material configuration from file
|
|
|
|
!> @details Reads the material configuration file, where solverJobName.materialConfig takes
|
|
|
|
!! precedence over material.config. Stores the raw strings and the positions of delimiters for the
|
|
|
|
!! parts 'homogenization', 'crystallite', 'phase', 'texture', and 'microstucture'
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-14 10:09:49 +05:30
|
|
|
module config
|
2018-06-09 00:31:58 +05:30
|
|
|
use prec, only: &
|
|
|
|
pReal, &
|
|
|
|
pInt
|
2018-06-10 22:08:31 +05:30
|
|
|
|
2018-06-09 00:31:58 +05:30
|
|
|
implicit none
|
2018-06-10 22:08:31 +05:30
|
|
|
private
|
2018-06-20 03:23:14 +05:30
|
|
|
type, private :: tPartitionedString
|
|
|
|
character(len=:), allocatable :: val
|
|
|
|
integer(pInt), dimension(:), allocatable :: pos
|
|
|
|
end type tPartitionedString
|
|
|
|
|
|
|
|
type, public :: tPartitionedStringList
|
|
|
|
type(tPartitionedString) :: string
|
|
|
|
type(tPartitionedStringList), pointer :: next => null()
|
2018-06-22 03:18:34 +05:30
|
|
|
|
2018-06-20 03:23:14 +05:30
|
|
|
contains
|
|
|
|
procedure :: add => add
|
|
|
|
procedure :: show => show
|
2018-06-26 22:16:52 +05:30
|
|
|
procedure :: free => free
|
2018-06-20 03:23:14 +05:30
|
|
|
|
2018-06-22 02:04:32 +05:30
|
|
|
procedure :: keyExists => keyExists
|
|
|
|
procedure :: countKeys => countKeys
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
procedure :: getFloat => getFloat
|
|
|
|
procedure :: getInt => getInt
|
2018-06-22 03:18:34 +05:30
|
|
|
procedure :: getString => getString
|
|
|
|
|
|
|
|
procedure :: getFloats => getFloats
|
2018-06-20 03:23:14 +05:30
|
|
|
procedure :: getInts => getInts
|
2018-06-22 03:18:34 +05:30
|
|
|
procedure :: getStrings => getStrings
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
end type tPartitionedStringList
|
|
|
|
|
|
|
|
type(tPartitionedStringList), public :: emptyList
|
|
|
|
|
2018-06-26 21:03:25 +05:30
|
|
|
type(tPartitionedStringList), public, protected, allocatable, dimension(:) :: & ! QUESTION: rename to config_XXX?
|
2018-06-27 00:24:54 +05:30
|
|
|
config_phase, &
|
|
|
|
config_microstructure, &
|
|
|
|
config_homogenization, &
|
|
|
|
config_texture, &
|
|
|
|
config_crystallite
|
2018-06-10 22:08:31 +05:30
|
|
|
|
2018-06-09 00:31:58 +05:30
|
|
|
character(len=64), dimension(:), allocatable, public, protected :: &
|
|
|
|
phase_name, & !< name of each phase
|
|
|
|
homogenization_name, & !< name of each homogenization
|
|
|
|
crystallite_name, & !< name of each crystallite setting
|
|
|
|
microstructure_name, & !< name of each microstructure
|
|
|
|
texture_name !< name of each texture
|
2018-06-10 22:08:31 +05:30
|
|
|
|
|
|
|
! ToDo: make private, no one needs to know that
|
2018-06-10 21:31:52 +05:30
|
|
|
character(len=*), parameter, public :: &
|
2018-06-09 00:31:58 +05:30
|
|
|
MATERIAL_partHomogenization = 'homogenization', & !< keyword for homogenization part
|
|
|
|
MATERIAL_partCrystallite = 'crystallite', & !< keyword for crystallite part
|
2018-06-10 22:08:31 +05:30
|
|
|
MATERIAL_partPhase = 'phase', & !< keyword for phase part
|
2018-06-27 00:20:06 +05:30
|
|
|
MATERIAL_partMicrostructure = 'microstructure' !< keyword for microstructure part
|
|
|
|
character(len=*), parameter, private :: &
|
2018-06-09 00:31:58 +05:30
|
|
|
MATERIAL_partTexture = 'texture' !< keyword for texture part
|
|
|
|
|
2018-06-27 00:24:54 +05:30
|
|
|
! ToDo: Remove, use size(config_phase) etc
|
2018-06-09 00:31:58 +05:30
|
|
|
integer(pInt), public, protected :: &
|
|
|
|
material_Nphase, & !< number of phases
|
|
|
|
material_Nhomogenization, & !< number of homogenizations
|
|
|
|
material_Nmicrostructure, & !< number of microstructures
|
|
|
|
material_Ncrystallite !< number of crystallite settings
|
|
|
|
|
2018-06-10 22:08:31 +05:30
|
|
|
! ToDo: make private, no one needs to know that
|
2018-06-10 21:31:52 +05:30
|
|
|
character(len=*), parameter, public :: &
|
|
|
|
MATERIAL_configFile = 'material.config', & !< generic name for material configuration file
|
|
|
|
MATERIAL_localFileExt = 'materialConfig' !< extension of solver job name depending material configuration file
|
2018-06-09 00:31:58 +05:30
|
|
|
|
2018-06-20 03:23:14 +05:30
|
|
|
|
2018-06-27 00:00:41 +05:30
|
|
|
public :: &
|
|
|
|
config_init, &
|
|
|
|
config_deallocate
|
2018-06-10 22:08:31 +05:30
|
|
|
|
2018-06-09 00:31:58 +05:30
|
|
|
contains
|
|
|
|
|
2018-06-27 00:00:41 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief reads material.config and stores its content per part
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-14 10:09:49 +05:30
|
|
|
subroutine config_init()
|
2018-06-09 00:31:58 +05:30
|
|
|
#if defined(__GFORTRAN__) || __INTEL_COMPILER >= 1800
|
|
|
|
use, intrinsic :: iso_fortran_env, only: &
|
|
|
|
compiler_version, &
|
|
|
|
compiler_options
|
|
|
|
#endif
|
2018-07-16 15:12:58 +05:30
|
|
|
use DAMASK_interface, only: &
|
|
|
|
getSolverJobName
|
2018-06-09 00:31:58 +05:30
|
|
|
use IO, only: &
|
|
|
|
IO_error, &
|
|
|
|
IO_lc, &
|
2018-07-16 15:12:58 +05:30
|
|
|
IO_recursiveRead, &
|
2018-06-09 00:31:58 +05:30
|
|
|
IO_getTag, &
|
|
|
|
IO_timeStamp, &
|
|
|
|
IO_EOF
|
|
|
|
use debug, only: &
|
|
|
|
debug_level, &
|
|
|
|
debug_material, &
|
2018-06-10 21:31:52 +05:30
|
|
|
debug_levelBasic
|
2018-06-09 00:31:58 +05:30
|
|
|
|
|
|
|
implicit none
|
2018-08-04 23:09:50 +05:30
|
|
|
integer(pInt) :: myDebug,i
|
2018-06-09 00:31:58 +05:30
|
|
|
|
2018-07-16 15:38:22 +05:30
|
|
|
character(len=256) :: &
|
2018-06-10 22:08:31 +05:30
|
|
|
line, &
|
|
|
|
part
|
2018-07-16 15:38:22 +05:30
|
|
|
character(len=256), dimension(:), allocatable :: fileContent
|
2018-08-04 23:09:50 +05:30
|
|
|
logical :: fileExists
|
2018-06-09 00:31:58 +05:30
|
|
|
|
2018-06-26 11:08:03 +05:30
|
|
|
write(6,'(/,a)') ' <<<+- config init -+>>>'
|
2018-06-09 00:31:58 +05:30
|
|
|
write(6,'(a15,a)') ' Current time: ',IO_timeStamp()
|
|
|
|
#include "compilation_info.f90"
|
|
|
|
|
2018-06-27 00:00:41 +05:30
|
|
|
myDebug = debug_level(debug_material)
|
|
|
|
|
2018-08-04 23:09:50 +05:30
|
|
|
inquire(file=trim(getSolverJobName())//'.'//material_localFileExt,exist=fileExists)
|
|
|
|
if(fileExists) then
|
2018-07-16 15:12:58 +05:30
|
|
|
fileContent = IO_recursiveRead(trim(getSolverJobName())//'.'//material_localFileExt)
|
|
|
|
else
|
2018-08-04 23:09:50 +05:30
|
|
|
inquire(file='material.config',exist=fileExists)
|
|
|
|
if(.not. fileExists) call IO_error(100_pInt,ext_msg='material.config')
|
2018-07-16 15:12:58 +05:30
|
|
|
fileContent = IO_recursiveRead('material.config')
|
|
|
|
endif
|
2018-06-09 00:31:58 +05:30
|
|
|
|
2018-07-16 15:12:58 +05:30
|
|
|
do i=1, size(fileContent)
|
|
|
|
line = trim(fileContent(i))
|
2018-06-09 00:31:58 +05:30
|
|
|
part = IO_lc(IO_getTag(line,'<','>'))
|
|
|
|
select case (trim(part))
|
|
|
|
|
|
|
|
case (trim(material_partPhase))
|
2018-08-04 23:09:50 +05:30
|
|
|
call parseFile(line,phase_name,config_phase,fileContent(i+1:))
|
2018-06-09 00:31:58 +05:30
|
|
|
if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Phase parsed'; flush(6)
|
|
|
|
|
|
|
|
case (trim(material_partMicrostructure))
|
2018-07-16 15:12:58 +05:30
|
|
|
call parseFile(line,microstructure_name,config_microstructure,fileContent(i+1:))
|
2018-06-09 00:31:58 +05:30
|
|
|
if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Microstructure parsed'; flush(6)
|
|
|
|
|
|
|
|
case (trim(material_partCrystallite))
|
2018-07-16 15:12:58 +05:30
|
|
|
call parseFile(line,crystallite_name,config_crystallite,fileContent(i+1:))
|
2018-06-09 00:31:58 +05:30
|
|
|
if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Crystallite parsed'; flush(6)
|
|
|
|
|
|
|
|
case (trim(material_partHomogenization))
|
2018-07-16 15:12:58 +05:30
|
|
|
call parseFile(line,homogenization_name,config_homogenization,fileContent(i+1:))
|
2018-06-09 00:31:58 +05:30
|
|
|
if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Homogenization parsed'; flush(6)
|
|
|
|
|
|
|
|
case (trim(material_partTexture))
|
2018-07-16 15:12:58 +05:30
|
|
|
call parseFile(line,texture_name,config_texture,fileContent(i+1:))
|
2018-06-09 00:31:58 +05:30
|
|
|
if (iand(myDebug,debug_levelBasic) /= 0_pInt) write(6,'(a)') ' Texture parsed'; flush(6)
|
|
|
|
|
|
|
|
end select
|
|
|
|
|
|
|
|
enddo
|
2018-06-09 17:18:37 +05:30
|
|
|
|
2018-06-27 00:24:54 +05:30
|
|
|
material_Nhomogenization = size(config_homogenization)
|
2018-06-09 17:18:37 +05:30
|
|
|
if (material_Nhomogenization < 1_pInt) call IO_error(160_pInt,ext_msg=material_partHomogenization)
|
2018-06-27 00:24:54 +05:30
|
|
|
material_Nmicrostructure = size(config_microstructure)
|
2018-06-09 17:18:37 +05:30
|
|
|
if (material_Nmicrostructure < 1_pInt) call IO_error(160_pInt,ext_msg=material_partMicrostructure)
|
2018-06-27 00:24:54 +05:30
|
|
|
material_Ncrystallite = size(config_crystallite)
|
2018-06-09 17:18:37 +05:30
|
|
|
if (material_Ncrystallite < 1_pInt) call IO_error(160_pInt,ext_msg=material_partCrystallite)
|
2018-06-27 00:24:54 +05:30
|
|
|
material_Nphase = size(config_phase)
|
2018-06-09 17:18:37 +05:30
|
|
|
if (material_Nphase < 1_pInt) call IO_error(160_pInt,ext_msg=material_partPhase)
|
2018-06-27 00:24:54 +05:30
|
|
|
if (size(config_texture) < 1_pInt) call IO_error(160_pInt,ext_msg=material_partTexture)
|
2018-06-09 17:18:37 +05:30
|
|
|
|
2018-06-14 10:09:49 +05:30
|
|
|
end subroutine config_init
|
2018-06-09 00:31:58 +05:30
|
|
|
|
2018-06-26 22:16:52 +05:30
|
|
|
|
2018-06-09 00:31:58 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-26 22:16:52 +05:30
|
|
|
!> @brief parses the material.config file
|
2018-06-09 00:31:58 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-14 10:05:28 +05:30
|
|
|
subroutine parseFile(line,&
|
2018-07-16 15:12:58 +05:30
|
|
|
sectionNames,part,fileContent)
|
2018-06-09 00:31:58 +05:30
|
|
|
use IO, only: &
|
|
|
|
IO_error, &
|
|
|
|
IO_lc, &
|
|
|
|
IO_getTag, &
|
|
|
|
IO_isBlank, &
|
|
|
|
IO_stringValue, &
|
2018-07-16 15:12:58 +05:30
|
|
|
IO_stringPos
|
2018-06-09 00:31:58 +05:30
|
|
|
|
|
|
|
implicit none
|
2018-06-10 21:31:52 +05:30
|
|
|
character(len=*), dimension(:), allocatable, intent(inout) :: sectionNames
|
2018-07-16 15:12:58 +05:30
|
|
|
type(tPartitionedStringList), allocatable, dimension(:), intent(out) :: part
|
2018-07-16 15:38:22 +05:30
|
|
|
character(len=256), dimension(:), intent(in) :: fileContent
|
|
|
|
character(len=256),intent(out) :: line
|
2018-06-09 00:31:58 +05:30
|
|
|
|
|
|
|
integer(pInt), allocatable, dimension(:) :: chunkPos
|
2018-07-16 15:12:58 +05:30
|
|
|
integer(pInt) :: s,i
|
2018-06-10 21:31:52 +05:30
|
|
|
character(len=64) :: tag
|
2018-06-09 00:31:58 +05:30
|
|
|
logical :: echo
|
2018-06-11 04:12:42 +05:30
|
|
|
|
|
|
|
echo = .false.
|
2018-06-09 17:18:37 +05:30
|
|
|
allocate(part(0))
|
2018-06-09 00:31:58 +05:30
|
|
|
|
2018-06-10 21:31:52 +05:30
|
|
|
s = 0_pInt
|
2018-07-16 15:12:58 +05:30
|
|
|
do i=1, size(fileContent)
|
|
|
|
line = trim(fileContent(i))
|
2018-06-09 00:31:58 +05:30
|
|
|
if (IO_isBlank(line)) cycle ! skip empty lines
|
2018-07-16 15:12:58 +05:30
|
|
|
if (IO_getTag(line,'<','>') /= '') exit
|
2018-06-09 00:31:58 +05:30
|
|
|
nextSection: if (IO_getTag(line,'[',']') /= '') then
|
2018-06-10 21:31:52 +05:30
|
|
|
s = s + 1_pInt
|
2018-06-09 17:18:37 +05:30
|
|
|
part = [part, emptyList]
|
2018-06-10 21:31:52 +05:30
|
|
|
tag = IO_getTag(line,'[',']')
|
|
|
|
GfortranBug86033: if (.not. allocated(sectionNames)) then
|
|
|
|
allocate(sectionNames(1),source=tag)
|
2018-06-09 00:31:58 +05:30
|
|
|
else GfortranBug86033
|
2018-06-10 21:31:52 +05:30
|
|
|
sectionNames = [sectionNames,tag]
|
2018-06-09 00:31:58 +05:30
|
|
|
endif GfortranBug86033
|
2018-06-26 21:03:25 +05:30
|
|
|
cycle
|
2018-06-09 00:31:58 +05:30
|
|
|
endif nextSection
|
|
|
|
chunkPos = IO_stringPos(line)
|
|
|
|
tag = IO_lc(IO_stringValue(trim(line),chunkPos,1_pInt)) ! extract key
|
2018-06-10 21:31:52 +05:30
|
|
|
inSection: if (s > 0_pInt) then
|
|
|
|
call part(s)%add(IO_lc(trim(line)))
|
2018-06-09 00:31:58 +05:30
|
|
|
else inSection
|
|
|
|
echo = (trim(tag) == '/echo/')
|
|
|
|
endif inSection
|
|
|
|
enddo
|
|
|
|
|
2018-06-10 22:08:31 +05:30
|
|
|
if (echo) then
|
|
|
|
do s = 1, size(sectionNames)
|
|
|
|
call part(s)%show()
|
|
|
|
end do
|
|
|
|
end if
|
2018-06-26 22:16:52 +05:30
|
|
|
|
2018-06-09 17:18:37 +05:30
|
|
|
end subroutine parseFile
|
2018-06-09 00:31:58 +05:30
|
|
|
|
2018-08-04 23:09:50 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief deallocates the linked lists that store the content of the configuration files
|
2018-08-21 11:11:10 +05:30
|
|
|
! commenting out removes erratic errors with gfortran 7.3
|
2018-08-04 23:09:50 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-27 00:00:41 +05:30
|
|
|
subroutine config_deallocate(what)
|
|
|
|
use IO, only: &
|
|
|
|
IO_error
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
character(len=*), intent(in) :: what
|
|
|
|
integer(pInt) :: i
|
|
|
|
|
2018-08-21 11:11:10 +05:30
|
|
|
! select case(what)
|
|
|
|
!
|
|
|
|
! case('material.config/phase')
|
|
|
|
! do i=1, size(config_phase)
|
|
|
|
! call config_phase(i)%free
|
|
|
|
! enddo
|
|
|
|
! deallocate(config_phase)
|
|
|
|
!
|
|
|
|
! case('material.config/microstructure')
|
|
|
|
! do i=1, size(config_microstructure)
|
|
|
|
! call config_microstructure(i)%free
|
|
|
|
! enddo
|
|
|
|
! deallocate(config_microstructure)
|
|
|
|
!
|
|
|
|
! case('material.config/crystallite')
|
|
|
|
! do i=1, size(config_crystallite)
|
|
|
|
! call config_crystallite(i)%free
|
|
|
|
! enddo
|
|
|
|
! deallocate(config_crystallite)
|
|
|
|
!
|
|
|
|
! case('material.config/homogenization')
|
|
|
|
! do i=1, size(config_homogenization)
|
|
|
|
! call config_homogenization(i)%free
|
|
|
|
! enddo
|
|
|
|
! deallocate(config_homogenization)
|
|
|
|
!
|
|
|
|
! case('material.config/texture')
|
|
|
|
! do i=1, size(config_texture)
|
|
|
|
! call config_texture(i)%free
|
|
|
|
! enddo
|
|
|
|
! deallocate(config_texture)
|
|
|
|
!
|
|
|
|
! case default
|
|
|
|
! call IO_error(0_pInt,ext_msg='config_deallocate')
|
|
|
|
!
|
|
|
|
! end select
|
2018-06-27 00:00:41 +05:30
|
|
|
|
|
|
|
end subroutine config_deallocate
|
|
|
|
|
|
|
|
|
2018-08-04 23:09:50 +05:30
|
|
|
!##################################################################################################
|
|
|
|
! The folowing functions are part of the tPartitionedStringList object
|
|
|
|
!##################################################################################################
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-06-20 03:23:14 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief add element
|
|
|
|
!> @details Adds a string together with the start/end position of chunks in this string. The new
|
|
|
|
!! element is added at the end of the list. Empty strings are not added. All strings are converted
|
|
|
|
!! to lower case
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
subroutine add(this,string)
|
|
|
|
use IO, only: &
|
|
|
|
IO_isBlank, &
|
|
|
|
IO_lc, &
|
|
|
|
IO_stringPos
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
class(tPartitionedStringList), target, intent(in) :: this
|
|
|
|
character(len=*), intent(in) :: string
|
|
|
|
type(tPartitionedStringList), pointer :: new, item
|
|
|
|
|
|
|
|
if (IO_isBlank(string)) return
|
|
|
|
|
|
|
|
allocate(new)
|
|
|
|
new%string%val = IO_lc (trim(string))
|
|
|
|
new%string%pos = IO_stringPos(trim(string))
|
|
|
|
|
|
|
|
item => this
|
|
|
|
do while (associated(item%next))
|
|
|
|
item => item%next
|
|
|
|
enddo
|
|
|
|
item%next => new
|
|
|
|
|
|
|
|
end subroutine add
|
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief prints all elements
|
|
|
|
!> @details Strings are printed in order of insertion (FIFO)
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
subroutine show(this)
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
class(tPartitionedStringList) :: this
|
|
|
|
type(tPartitionedStringList), pointer :: item
|
|
|
|
|
|
|
|
item => this%next
|
|
|
|
do while (associated(item))
|
|
|
|
write(6,'(a)') trim(item%string%val)
|
|
|
|
item => item%next
|
|
|
|
end do
|
|
|
|
|
|
|
|
end subroutine show
|
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-26 22:16:52 +05:30
|
|
|
!> @brief cleans entire list
|
2018-08-21 11:11:10 +05:30
|
|
|
!> @details list head remains alive
|
2018-06-20 03:23:14 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-26 22:16:52 +05:30
|
|
|
subroutine free(this)
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
class(tPartitionedStringList), target, intent(in) :: this
|
|
|
|
type(tPartitionedStringList), pointer :: new, item
|
|
|
|
|
2018-06-27 12:34:14 +05:30
|
|
|
if (.not. associated(this%next)) return
|
|
|
|
|
2018-06-26 22:16:52 +05:30
|
|
|
item => this%next
|
|
|
|
do while (associated(item%next))
|
|
|
|
new => item
|
|
|
|
deallocate(item)
|
|
|
|
item => new%next
|
|
|
|
enddo
|
|
|
|
deallocate(item)
|
|
|
|
|
|
|
|
end subroutine free
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief reports wether a given key (string value at first position) exists in the list
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-22 02:04:32 +05:30
|
|
|
logical function keyExists(this,key)
|
2018-06-20 03:23:14 +05:30
|
|
|
use IO, only: &
|
|
|
|
IO_stringValue
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
class(tPartitionedStringList), intent(in) :: this
|
|
|
|
character(len=*), intent(in) :: key
|
|
|
|
type(tPartitionedStringList), pointer :: item
|
|
|
|
|
2018-06-22 02:04:32 +05:30
|
|
|
keyExists = .false.
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
item => this%next
|
2018-06-22 02:04:32 +05:30
|
|
|
do while (associated(item) .and. .not. keyExists)
|
|
|
|
keyExists = trim(IO_stringValue(item%string%val,item%string%pos,1)) == trim(key)
|
2018-06-20 03:23:14 +05:30
|
|
|
item => item%next
|
|
|
|
end do
|
|
|
|
|
2018-06-22 02:04:32 +05:30
|
|
|
end function keyExists
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
!> @brief count number of key appearances
|
|
|
|
!> @details traverses list and counts each occurrence of specified key
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-22 02:04:32 +05:30
|
|
|
integer(pInt) function countKeys(this,key)
|
2018-06-20 03:23:14 +05:30
|
|
|
use IO, only: &
|
|
|
|
IO_stringValue
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
|
|
|
|
class(tPartitionedStringList), intent(in) :: this
|
|
|
|
character(len=*), intent(in) :: key
|
|
|
|
type(tPartitionedStringList), pointer :: item
|
|
|
|
|
2018-06-22 02:04:32 +05:30
|
|
|
countKeys = 0_pInt
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
item => this%next
|
|
|
|
do while (associated(item))
|
|
|
|
if (trim(IO_stringValue(item%string%val,item%string%pos,1)) == trim(key)) &
|
2018-06-22 02:04:32 +05:30
|
|
|
countKeys = countKeys + 1_pInt
|
2018-06-20 03:23:14 +05:30
|
|
|
item => item%next
|
|
|
|
end do
|
|
|
|
|
2018-06-22 02:04:32 +05:30
|
|
|
end function countKeys
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-22 03:18:34 +05:30
|
|
|
!> @brief gets float value of for a given key from a linked list
|
|
|
|
!> @details gets the last value if the key occurs more than once. If key is not found exits with
|
|
|
|
!! error unless default is given
|
2018-06-20 03:23:14 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
real(pReal) function getFloat(this,key,defaultVal)
|
|
|
|
use IO, only : &
|
|
|
|
IO_error, &
|
|
|
|
IO_stringValue, &
|
|
|
|
IO_FloatValue
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
class(tPartitionedStringList), intent(in) :: this
|
|
|
|
character(len=*), intent(in) :: key
|
|
|
|
real(pReal), intent(in), optional :: defaultVal
|
|
|
|
type(tPartitionedStringList), pointer :: item
|
|
|
|
logical :: found
|
|
|
|
|
|
|
|
found = present(defaultVal)
|
2018-06-26 21:03:25 +05:30
|
|
|
if (found) getFloat = defaultVal
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
item => this%next
|
|
|
|
do while (associated(item))
|
|
|
|
if (trim(IO_stringValue(item%string%val,item%string%pos,1)) == trim(key)) then
|
|
|
|
found = .true.
|
|
|
|
if (item%string%pos(1) < 2_pInt) call IO_error(143_pInt,ext_msg=key)
|
|
|
|
getFloat = IO_FloatValue(item%string%val,item%string%pos,2)
|
|
|
|
endif
|
|
|
|
item => item%next
|
|
|
|
end do
|
|
|
|
|
|
|
|
if (.not. found) call IO_error(140_pInt,ext_msg=key)
|
|
|
|
|
|
|
|
end function getFloat
|
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-22 03:18:34 +05:30
|
|
|
!> @brief gets integer value of for a given key from a linked list
|
|
|
|
!> @details gets the last value if the key occurs more than once. If key is not found exits with
|
|
|
|
!! error unless default is given
|
2018-06-20 03:23:14 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
integer(pInt) function getInt(this,key,defaultVal)
|
|
|
|
use IO, only: &
|
|
|
|
IO_error, &
|
|
|
|
IO_stringValue, &
|
|
|
|
IO_IntValue
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
class(tPartitionedStringList), intent(in) :: this
|
|
|
|
character(len=*), intent(in) :: key
|
|
|
|
integer(pInt), intent(in), optional :: defaultVal
|
|
|
|
type(tPartitionedStringList), pointer :: item
|
|
|
|
logical :: found
|
|
|
|
|
|
|
|
found = present(defaultVal)
|
2018-06-26 21:03:25 +05:30
|
|
|
if (found) getInt = defaultVal
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
item => this%next
|
|
|
|
do while (associated(item))
|
|
|
|
if (trim(IO_stringValue(item%string%val,item%string%pos,1)) == trim(key)) then
|
|
|
|
found = .true.
|
|
|
|
if (item%string%pos(1) < 2_pInt) call IO_error(143_pInt,ext_msg=key)
|
|
|
|
getInt = IO_IntValue(item%string%val,item%string%pos,2)
|
|
|
|
endif
|
|
|
|
item => item%next
|
|
|
|
end do
|
|
|
|
|
|
|
|
if (.not. found) call IO_error(140_pInt,ext_msg=key)
|
|
|
|
|
|
|
|
end function getInt
|
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-22 03:18:34 +05:30
|
|
|
!> @brief gets string value of for a given key from a linked list
|
|
|
|
!> @details gets the last value if the key occurs more than once. If key is not found exits with
|
|
|
|
!! error unless default is given. If raw is true, the the complete string is returned, otherwise
|
|
|
|
!! the individual chunks are returned
|
2018-06-20 03:23:14 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
|
|
|
character(len=65536) function getString(this,key,defaultVal,raw)
|
|
|
|
use IO, only: &
|
|
|
|
IO_error, &
|
|
|
|
IO_stringValue
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
class(tPartitionedStringList), intent(in) :: this
|
|
|
|
character(len=*), intent(in) :: key
|
|
|
|
character(len=65536), intent(in), optional :: defaultVal
|
|
|
|
logical, intent(in), optional :: raw
|
|
|
|
type(tPartitionedStringList), pointer :: item
|
|
|
|
logical :: found, &
|
2018-06-26 21:03:25 +05:30
|
|
|
whole
|
2018-06-20 03:23:14 +05:30
|
|
|
|
2018-06-26 21:03:25 +05:30
|
|
|
whole = merge(raw,.false.,present(raw)) ! whole string or white space splitting
|
2018-06-20 03:23:14 +05:30
|
|
|
found = present(defaultVal)
|
2018-06-26 22:39:08 +05:30
|
|
|
if (found) then
|
2018-06-26 22:48:23 +05:30
|
|
|
getString = trim(defaultVal)
|
2018-06-26 22:39:08 +05:30
|
|
|
if (len_trim(getString) /= len_trim(defaultVal)) call IO_error(0_pInt,ext_msg='getString')
|
|
|
|
endif
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
item => this%next
|
|
|
|
do while (associated(item))
|
|
|
|
if (trim(IO_stringValue(item%string%val,item%string%pos,1)) == trim(key)) then
|
|
|
|
found = .true.
|
|
|
|
if (item%string%pos(1) < 2_pInt) call IO_error(143_pInt,ext_msg=key)
|
|
|
|
|
2018-06-26 21:03:25 +05:30
|
|
|
if (whole) then
|
2018-06-20 03:23:14 +05:30
|
|
|
getString = trim(item%string%val(item%string%pos(4):)) ! raw string starting a second chunk
|
2018-06-26 21:03:25 +05:30
|
|
|
else
|
|
|
|
getString = IO_StringValue(item%string%val,item%string%pos,2)
|
2018-06-20 03:23:14 +05:30
|
|
|
endif
|
|
|
|
endif
|
|
|
|
item => item%next
|
|
|
|
end do
|
|
|
|
|
|
|
|
if (.not. found) call IO_error(140_pInt,ext_msg=key)
|
2018-06-26 22:39:08 +05:30
|
|
|
|
2018-06-20 03:23:14 +05:30
|
|
|
end function getString
|
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-22 03:18:34 +05:30
|
|
|
!> @brief gets array of float values of for a given key from a linked list
|
|
|
|
!> @details for cumulative keys, "()", values from all occurrences are return. Otherwise only all
|
|
|
|
!! values from the last occurrence. If key is not found exits with error unless default is given.
|
2018-06-20 03:23:14 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-27 21:34:06 +05:30
|
|
|
function getFloats(this,key,defaultVal,requiredShape)
|
2018-06-22 03:18:34 +05:30
|
|
|
use IO, only: &
|
|
|
|
IO_error, &
|
|
|
|
IO_stringValue, &
|
|
|
|
IO_FloatValue
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
implicit none
|
2018-06-22 03:18:34 +05:30
|
|
|
real(pReal), dimension(:), allocatable :: getFloats
|
|
|
|
class(tPartitionedStringList), intent(in) :: this
|
|
|
|
character(len=*), intent(in) :: key
|
|
|
|
real(pReal), dimension(:), intent(in), optional :: defaultVal
|
2018-06-27 21:34:06 +05:30
|
|
|
integer(pInt), dimension(:), intent(in), optional :: requiredShape
|
2018-06-22 03:18:34 +05:30
|
|
|
type(tPartitionedStringList), pointer :: item
|
|
|
|
integer(pInt) :: i
|
2018-06-20 03:23:14 +05:30
|
|
|
logical :: found, &
|
2018-06-22 03:18:34 +05:30
|
|
|
cumulative
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
cumulative = (key(1:1) == '(' .and. key(len_trim(key):len_trim(key)) == ')')
|
|
|
|
found = .false.
|
|
|
|
|
2018-06-22 03:18:34 +05:30
|
|
|
allocate(getFloats(0))
|
|
|
|
|
2018-06-20 03:23:14 +05:30
|
|
|
item => this%next
|
|
|
|
do while (associated(item))
|
|
|
|
if (trim(IO_stringValue(item%string%val,item%string%pos,1)) == trim(key)) then
|
|
|
|
found = .true.
|
2018-06-26 22:48:23 +05:30
|
|
|
if (.not. cumulative) getFloats = [real(pReal)::]
|
2018-06-20 03:23:14 +05:30
|
|
|
if (item%string%pos(1) < 2_pInt) call IO_error(143_pInt,ext_msg=key)
|
2018-06-22 03:18:34 +05:30
|
|
|
do i = 2_pInt, item%string%pos(1)
|
|
|
|
getFloats = [getFloats,IO_FloatValue(item%string%val,item%string%pos,i)]
|
|
|
|
enddo
|
2018-06-20 03:23:14 +05:30
|
|
|
endif
|
|
|
|
item => item%next
|
|
|
|
end do
|
|
|
|
|
2018-06-26 21:03:25 +05:30
|
|
|
if (.not. found) then
|
|
|
|
if (present(defaultVal)) then; getFloats = defaultVal; else; call IO_error(140_pInt,ext_msg=key); endif
|
2018-06-20 03:23:14 +05:30
|
|
|
endif
|
|
|
|
|
2018-06-22 03:18:34 +05:30
|
|
|
end function getFloats
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-22 03:18:34 +05:30
|
|
|
!> @brief gets array of integer values of for a given key from a linked list
|
|
|
|
!> @details for cumulative keys, "()", values from all occurrences are return. Otherwise only all
|
|
|
|
!! values from the last occurrence. If key is not found exits with error unless default is given.
|
2018-06-20 03:23:14 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-27 21:34:06 +05:30
|
|
|
function getInts(this,key,defaultVal,requiredShape)
|
2018-06-20 03:23:14 +05:30
|
|
|
use IO, only: &
|
|
|
|
IO_error, &
|
|
|
|
IO_stringValue, &
|
|
|
|
IO_IntValue
|
|
|
|
|
|
|
|
implicit none
|
|
|
|
integer(pInt), dimension(:), allocatable :: getInts
|
|
|
|
class(tPartitionedStringList), intent(in) :: this
|
|
|
|
character(len=*), intent(in) :: key
|
2018-06-27 21:34:06 +05:30
|
|
|
integer(pInt), dimension(:), intent(in), optional :: defaultVal, &
|
|
|
|
requiredShape
|
2018-06-20 03:23:14 +05:30
|
|
|
type(tPartitionedStringList), pointer :: item
|
|
|
|
integer(pInt) :: i
|
|
|
|
logical :: found, &
|
|
|
|
cumulative
|
|
|
|
|
|
|
|
cumulative = (key(1:1) == '(' .and. key(len_trim(key):len_trim(key)) == ')')
|
|
|
|
found = .false.
|
|
|
|
|
|
|
|
allocate(getInts(0))
|
|
|
|
|
|
|
|
item => this%next
|
|
|
|
do while (associated(item))
|
|
|
|
if (trim(IO_stringValue(item%string%val,item%string%pos,1)) == trim(key)) then
|
|
|
|
found = .true.
|
2018-06-26 22:48:23 +05:30
|
|
|
if (.not. cumulative) getInts = [integer(pInt)::]
|
2018-06-20 03:23:14 +05:30
|
|
|
if (item%string%pos(1) < 2_pInt) call IO_error(143_pInt,ext_msg=key)
|
|
|
|
do i = 2_pInt, item%string%pos(1)
|
|
|
|
getInts = [getInts,IO_IntValue(item%string%val,item%string%pos,i)]
|
|
|
|
enddo
|
|
|
|
endif
|
|
|
|
item => item%next
|
|
|
|
end do
|
|
|
|
|
2018-06-26 21:03:25 +05:30
|
|
|
if (.not. found) then
|
|
|
|
if (present(defaultVal)) then; getInts = defaultVal; else; call IO_error(140_pInt,ext_msg=key); endif
|
2018-06-20 03:23:14 +05:30
|
|
|
endif
|
|
|
|
|
|
|
|
end function getInts
|
|
|
|
|
|
|
|
|
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-22 03:18:34 +05:30
|
|
|
!> @brief gets array of string values of for a given key from a linked list
|
|
|
|
!> @details for cumulative keys, "()", values from all occurrences are return. Otherwise only all
|
|
|
|
!! values from the last occurrence. If key is not found exits with error unless default is given.
|
|
|
|
!! If raw is true, the the complete string is returned, otherwise the individual chunks are returned
|
2018-06-20 03:23:14 +05:30
|
|
|
!--------------------------------------------------------------------------------------------------
|
2018-06-27 21:34:06 +05:30
|
|
|
function getStrings(this,key,defaultVal,requiredShape,raw)
|
2018-06-20 03:23:14 +05:30
|
|
|
use IO, only: &
|
|
|
|
IO_error, &
|
2018-06-22 03:18:34 +05:30
|
|
|
IO_StringValue
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
implicit none
|
2018-06-22 03:18:34 +05:30
|
|
|
character(len=65536),dimension(:), allocatable :: getStrings
|
|
|
|
class(tPartitionedStringList), intent(in) :: this
|
|
|
|
character(len=*), intent(in) :: key
|
|
|
|
character(len=65536),dimension(:), intent(in), optional :: defaultVal
|
2018-06-27 21:34:06 +05:30
|
|
|
integer(pInt), dimension(:), intent(in), optional :: requiredShape
|
2018-06-22 03:18:34 +05:30
|
|
|
logical, intent(in), optional :: raw
|
|
|
|
type(tPartitionedStringList), pointer :: item
|
|
|
|
character(len=65536) :: str
|
|
|
|
integer(pInt) :: i
|
|
|
|
logical :: found, &
|
2018-06-26 21:03:25 +05:30
|
|
|
whole, &
|
2018-06-22 03:18:34 +05:30
|
|
|
cumulative
|
2018-06-20 03:23:14 +05:30
|
|
|
|
|
|
|
cumulative = (key(1:1) == '(' .and. key(len_trim(key):len_trim(key)) == ')')
|
2018-06-26 21:03:25 +05:30
|
|
|
whole = merge(raw,.false.,present(raw))
|
2018-06-20 03:23:14 +05:30
|
|
|
found = .false.
|
|
|
|
|
|
|
|
item => this%next
|
|
|
|
do while (associated(item))
|
|
|
|
if (trim(IO_stringValue(item%string%val,item%string%pos,1)) == trim(key)) then
|
|
|
|
found = .true.
|
2018-06-22 03:18:34 +05:30
|
|
|
if (allocated(getStrings) .and. .not. cumulative) deallocate(getStrings)
|
2018-06-20 03:23:14 +05:30
|
|
|
if (item%string%pos(1) < 2_pInt) call IO_error(143_pInt,ext_msg=key)
|
2018-06-22 03:18:34 +05:30
|
|
|
|
|
|
|
notAllocated: if (.not. allocated(getStrings)) then
|
2018-06-26 21:03:25 +05:30
|
|
|
if (whole) then
|
|
|
|
str = item%string%val(item%string%pos(4):)
|
|
|
|
getStrings = [str]
|
|
|
|
else
|
2018-06-22 03:18:34 +05:30
|
|
|
str = IO_StringValue(item%string%val,item%string%pos,2_pInt)
|
|
|
|
allocate(getStrings(1),source=str)
|
|
|
|
do i=3_pInt,item%string%pos(1)
|
|
|
|
str = IO_StringValue(item%string%val,item%string%pos,i)
|
|
|
|
getStrings = [getStrings,str]
|
|
|
|
enddo
|
|
|
|
endif
|
|
|
|
else notAllocated
|
2018-06-26 21:03:25 +05:30
|
|
|
if (whole) then
|
2018-08-01 02:45:44 +05:30
|
|
|
str = item%string%val(item%string%pos(4):)
|
2018-06-26 21:03:25 +05:30
|
|
|
getStrings = [getStrings,str]
|
|
|
|
else
|
2018-06-22 03:18:34 +05:30
|
|
|
do i=2_pInt,item%string%pos(1)
|
|
|
|
str = IO_StringValue(item%string%val,item%string%pos,i)
|
|
|
|
getStrings = [getStrings,str]
|
|
|
|
enddo
|
|
|
|
endif
|
|
|
|
endif notAllocated
|
2018-06-20 03:23:14 +05:30
|
|
|
endif
|
|
|
|
item => item%next
|
|
|
|
end do
|
|
|
|
|
2018-06-26 21:03:25 +05:30
|
|
|
if (.not. found) then
|
|
|
|
if (present(defaultVal)) then; getStrings = defaultVal; else; call IO_error(140_pInt,ext_msg=key); endif
|
2018-06-20 03:23:14 +05:30
|
|
|
endif
|
|
|
|
|
2018-06-22 03:18:34 +05:30
|
|
|
end function getStrings
|
|
|
|
|
|
|
|
|
2018-06-14 10:09:49 +05:30
|
|
|
end module config
|