PartMC 2.1.2
spec_file.F90
Go to the documentation of this file.
00001 ! Copyright (C) 2007-2011 Nicole Riemer and Matthew West
00002 ! Licensed under the GNU General Public License version 2 or (at your
00003 ! option) any later version. See the file COPYING for details.
00004 
00005 !> \file
00006 !> The pmc_spec_file module.
00007 
00008 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00009 
00010 !> \page spec_file_format Input File Format: Spec File Format
00011 !!
00012 !! All PartMC input files are in a text format. Each line consists of
00013 !! a <b>parameter name</b>, followed by the <b>parameter value</b>,
00014 !! and an optional comment starting with the # character. Blank lines
00015 !! and comment-only lines are permitted, and everything on a line
00016 !! after a # is completely ignored.
00017 !!
00018 !! Parameter names are strings (normally lowercase) without spaces,
00019 !! such as \c output_prefix or \c del_t. The case of parameter names
00020 !! is significant. The order of parameters in a file is not
00021 !! arbitrary. Instead, they must come in the prescribed order and
00022 !! cannot be skipped or rearranged.
00023 !!
00024 !! The parameter types are:
00025 !!   - \b string: a single string without spaces (case is significant)
00026 !!   - \b logical: a true/false value that can be the exact values
00027 !!     "yes", "y", "true", "t", or "1" (for true values), or "no",
00028 !!     "n", "false", "f", or "0" (for false values
00029 !!   - \b integer: a positive or negative integer (depending on
00030 !!     whether PartMC was compiled as 32bit or 64bit the maximum size
00031 !!     will vary)
00032 !!   - \b real: a floating point real number in Fortran syntax,
00033 !!     e.g. -1.45, 5.27e10 (the available precision and range is that
00034 !!     of whatever double precision meant during the compilation)
00035 !!   - \b complex: two real numbers separated by a space, giving the
00036 !!     real and imaginary parts of a complex number, respectively
00037 !!   - <b>real array</b>: a list of real numbers separated by spaces,
00038 !!     giving the entries of the array
00039 
00040 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00041 
00042 !> Reading formatted text input.
00043 module pmc_spec_file
00044 
00045   use pmc_spec_line
00046   use pmc_util
00047   
00048   !> Maximum number of lines in an array.
00049   integer, parameter :: SPEC_FILE_MAX_LIST_LINES = 1000
00050 
00051   !> An input file with extra data for printing messages.
00052   !!
00053   !! An spec_file_t is just a simple wrapper around a Fortran unit
00054   !! number together with the filename and current line number. The
00055   !! line number is updated manually by the various \c spec_file_*()
00056   !! subroutine. To maintain its validity all file accesses must be
00057   !! done via the \c spec_file_*() subroutines, and no data should be
00058   !! accessed directly via \c spec_file%%unit.
00059   type spec_file_t
00060      !> Filename.
00061      character(len=SPEC_LINE_MAX_VAR_LEN) :: name
00062      !> Attached unit.
00063      integer :: unit
00064      !> Current line number.
00065      integer :: line_num
00066   end type spec_file_t
00067 
00068 contains
00069 
00070 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00071 
00072   !> Exit with an error message containing filename and line number.
00073   subroutine spec_file_die_msg(code, file, msg)
00074 
00075     !> Failure status code.
00076     integer, intent(in) :: code
00077     !> Spec file.
00078     type(spec_file_t), intent(in) :: file
00079     !> Error message.
00080     character(len=*), intent(in) :: msg
00081     
00082     call die_msg(code, "file " // trim(file%name) // " line " &
00083          // trim(integer_to_string(file%line_num)) // ": " // trim(msg))
00084 
00085   end subroutine spec_file_die_msg
00086 
00087 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00088 
00089   !> Open a spec file for reading.
00090   subroutine spec_file_open(filename, file)
00091 
00092     !> Name of file to open.
00093     character(len=*), intent(in) :: filename
00094     !> Spec file.
00095     type(spec_file_t), intent(out) :: file
00096 
00097     integer :: ios, unit
00098 
00099     file%name = trim(filename)
00100     file%unit = get_unit()
00101     open(unit=file%unit, status='old', file=file%name, iostat=ios)
00102     if (ios /= 0) then
00103        call die_msg(173932734, "unable to open file " // trim(file%name) &
00104             // " for reading: IOSTAT = " // trim(integer_to_string(ios)))
00105     end if
00106     file%line_num = 0
00107 
00108   end subroutine spec_file_open
00109 
00110 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00111 
00112   !> Close a spec file.
00113   subroutine spec_file_close(file)
00114 
00115     !> Spec file.
00116     type(spec_file_t), intent(in) :: file
00117 
00118     close(file%unit)
00119     call free_unit(file%unit)
00120 
00121   end subroutine spec_file_close
00122 
00123 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00124 
00125   !> Read a single line from a spec file, signaling if we have hit EOF.
00126   subroutine spec_file_read_line_raw(file, line, eof)
00127 
00128     !> Spec file.
00129     type(spec_file_t), intent(inout) :: file
00130     !> Complete line read.
00131     character(len=*), intent(out) :: line
00132     !> True if at EOF.
00133     logical, intent(out) :: eof
00134 
00135     integer :: ios, n_read
00136 
00137     file%line_num = file%line_num + 1
00138     eof = .false.
00139     line = "" ! needed for pgf95 for reading blank lines
00140     read(unit=file%unit, fmt='(a)', advance='no', end=100, eor=110, &
00141          iostat=ios) line
00142     if (ios /= 0) then
00143        call spec_file_die_msg(869855853, file, &
00144             'error reading: IOSTAT = ' // trim(integer_to_string(ios)))
00145     end if
00146     ! only reach here if we didn't hit end-of-record (end-of-line) in
00147     ! the above read, meaning the line was too long
00148     call spec_file_die_msg(468785871, file, &
00149          'line exceeds length: ' // trim(integer_to_string(len(line))))
00150 
00151 100 line = "" ! goto here if end-of-file was encountered immediately
00152     eof = .true.
00153 
00154 110 return ! goto here if end-of-record, meaning everything is ok
00155     
00156   end subroutine spec_file_read_line_raw
00157 
00158 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00159 
00160   !> Read the next line from the spec file that contains useful data
00161   !> (stripping comments and blank lines).
00162   subroutine spec_file_read_next_data_line(file, line, eof)
00163 
00164     !> Spec file.
00165     type(spec_file_t), intent(inout) :: file
00166     !> Complete line read.
00167     character(len=*), intent(out) :: line
00168     !> True if EOF encountered.
00169     logical, intent(out) :: eof
00170 
00171     logical :: done
00172 
00173     done = .false.
00174     do while (.not. done)
00175        call spec_file_read_line_raw(file, line, eof)
00176        if (eof) then
00177           done = .true.
00178        else
00179           call spec_line_strip_comment(line)
00180           call spec_line_tabs_to_spaces(line)
00181           call spec_line_strip_leading_spaces(line)
00182           if (len_trim(line) > 0) then
00183              done = .true.
00184           end if
00185        end if
00186     end do
00187 
00188   end subroutine spec_file_read_next_data_line
00189 
00190 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00191 
00192   !> Read a spec_line from the spec_file.
00193   subroutine spec_file_read_line(file, line, eof)
00194 
00195     !> Spec file.
00196     type(spec_file_t), intent(inout) :: file
00197     !> Spec line.
00198     type(spec_line_t), intent(inout) :: line
00199     !> True if EOF encountered.
00200     logical, intent(out) :: eof
00201 
00202     character(len=SPEC_LINE_MAX_LEN) :: line_string, rest
00203     integer i, n_data
00204     logical done
00205 
00206     call spec_file_read_next_data_line(file, line_string, eof)
00207     if (eof) return
00208 
00209     ! strip off the name
00210     i = index(line_string, ' ') ! first space
00211     if (i == 0) then
00212        call spec_file_die_msg(117442928, file, 'line contains no whitespace')
00213     end if
00214     if (i == 1) then
00215        call spec_file_die_msg(650916702, file, 'line starts with whitespace')
00216     end if
00217     if (i >= SPEC_LINE_MAX_VAR_LEN) then
00218        call spec_file_die_msg(170403881, file, 'line name longer than: ' &
00219             // trim(integer_to_string(SPEC_LINE_MAX_VAR_LEN)))
00220     end if
00221     line%name = line_string(1:(i-1))
00222     line_string = line_string(i:)
00223     call spec_line_strip_leading_spaces(line_string)
00224 
00225     ! figure out how many data items we have (consecutive non-spaces)
00226     n_data = 0
00227     rest = line_string
00228     done = .false.
00229     do while (.not. done)
00230        if (len_trim(rest) == 0) then ! only spaces left
00231           done = .true.
00232        else
00233           ! strip the data element
00234           n_data = n_data + 1
00235           i = index(rest, ' ') ! first space
00236           rest = rest(i:)
00237           call spec_line_strip_leading_spaces(rest)
00238        end if
00239     end do
00240 
00241     ! allocate the data and read out the data items
00242     call spec_line_deallocate(line)
00243     call spec_line_allocate_size(line, n_data)
00244     n_data = 0
00245     rest = line_string
00246     done = .false.
00247     do while (.not. done)
00248        if (len_trim(rest) == 0) then ! only spaces left
00249           done = .true.
00250        else
00251           ! strip the data element
00252           n_data = n_data + 1
00253           i = index(rest, ' ') ! first space
00254           if (i <= 1) then
00255              call spec_file_die_msg(332939443, file, &
00256                   'internal processing error')
00257           end if
00258           if (i >= SPEC_LINE_MAX_VAR_LEN) then
00259              call spec_file_die_msg(145508629, file, &
00260                   'data element ' // trim(integer_to_string(n_data)) &
00261                   // ' longer than: ' &
00262                   // trim(integer_to_string(SPEC_LINE_MAX_VAR_LEN)))
00263           end if
00264           line%data(n_data) = rest(1:(i-1))
00265           rest = rest(i:)
00266           call spec_line_strip_leading_spaces(rest)
00267        end if
00268     end do
00269     
00270   end subroutine spec_file_read_line
00271 
00272 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00273 
00274   !> Read a spec_line from the spec_file. This will always succeed or
00275   !> error out, so should only be called if we know there should be a
00276   !> valid line coming.
00277   subroutine spec_file_read_line_no_eof(file, line)
00278 
00279     !> Spec file.
00280     type(spec_file_t), intent(inout) :: file
00281     !> Spec line.
00282     type(spec_line_t), intent(inout) :: line
00283 
00284     logical :: eof
00285 
00286     call spec_file_read_line(file, line, eof)
00287     if (eof) then
00288        call spec_file_die_msg(358475502, file, 'unexpected end of file')
00289     end if
00290 
00291   end subroutine spec_file_read_line_no_eof
00292 
00293 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00294 
00295   !> Read a list of spec_lines from a file, stopping at max_lines
00296   !> or EOF, whichever comes first.
00297   subroutine spec_file_read_line_list(file, max_lines, line_list)
00298 
00299     !> Spec file.
00300     type(spec_file_t), intent(inout) :: file
00301     !> Max lines to read (0 = no max).
00302     integer, intent(in) :: max_lines
00303     !> List of spec_lines.
00304     type(spec_line_t), pointer :: line_list(:)
00305 
00306     logical :: eof
00307     integer :: i, num_lines
00308     type(spec_line_t) :: temp_line_list(SPEC_FILE_MAX_LIST_LINES)
00309 
00310     ! read file, working out how many lines we have
00311     num_lines = 0
00312     eof = .false.
00313     call spec_line_allocate(temp_line_list(num_lines + 1))
00314     call spec_file_read_line(file, temp_line_list(num_lines + 1), eof)
00315     if (eof) then
00316        call spec_line_deallocate(temp_line_list(num_lines + 1))
00317     end if
00318     do while (.not. eof)
00319        num_lines = num_lines + 1
00320        if (num_lines > SPEC_FILE_MAX_LIST_LINES) then
00321           call spec_file_die_msg(450564159, file, &
00322                'maximum number of lines exceeded')
00323        end if
00324        if (max_lines > 0) then
00325           if (num_lines >= max_lines) then
00326              eof = .true.
00327           end if
00328        end if
00329        if (.not. eof) then
00330           call spec_line_allocate(temp_line_list(num_lines + 1))
00331           call spec_file_read_line(file, temp_line_list(num_lines + 1), eof)
00332           if (eof) then
00333              call spec_line_deallocate(temp_line_list(num_lines + 1))
00334           end if
00335        end if
00336     end do
00337 
00338     ! copy data to actual list
00339     do i = 1,size(line_list)
00340        call spec_line_deallocate(line_list(i))
00341     end do
00342     deallocate(line_list)
00343     allocate(line_list(num_lines))
00344     do i = 1,num_lines
00345        call spec_line_allocate(line_list(i))
00346        call spec_line_copy(temp_line_list(i), line_list(i))
00347        call spec_line_deallocate(temp_line_list(i))
00348     end do
00349 
00350   end subroutine spec_file_read_line_list
00351 
00352 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00353 
00354   !> Read an array of spec_lines from a file, stopping at max_lines
00355   !> or EOF. All lines must have the same number of elements.
00356   subroutine spec_file_read_line_array(file, max_lines, line_array)
00357 
00358     !> Spec file.
00359     type(spec_file_t), intent(inout) :: file
00360     !> Max lines to read (0 = no max).
00361     integer, intent(in) :: max_lines
00362     !> Array of spec_lines,.
00363     type(spec_line_t), pointer :: line_array(:)
00364 
00365     integer :: i, line_length
00366 
00367     call spec_file_read_line_list(file, max_lines, line_array)
00368     if (size(line_array) > 0) then
00369        line_length = size(line_array(1)%data)
00370        do i = 2,size(line_array)
00371           if (size(line_array(i)%data) /= line_length) then
00372              call spec_file_die_msg(298076484, file, &
00373                   'lines have unequal numbers of entries for array')
00374           end if
00375        end do
00376     end if
00377     
00378   end subroutine spec_file_read_line_array
00379 
00380 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00381 
00382   !> Check that the name of the line data is as given.
00383   subroutine spec_file_check_line_name(file, line, name)
00384 
00385     !> Spec file.
00386     type(spec_file_t), intent(in) :: file
00387     !> Spec line.
00388     type(spec_line_t), intent(in) :: line
00389     !> Expected line name.
00390     character(len=*), intent(in) :: name
00391 
00392     if (line%name /= name) then
00393        call spec_file_die_msg(462932478, file, &
00394             'line must begin with: ' // trim(name) &
00395             // ' not: ' // trim(line%name))
00396     end if
00397 
00398   end subroutine spec_file_check_line_name
00399   
00400 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00401 
00402   !> Checks that the read_name is the same as name.
00403   subroutine spec_file_check_name(file, name, read_name)
00404     
00405     !> Spec file.
00406     type(spec_file_t), intent(inout) :: file
00407     !> Name that we should have.
00408     character(len=*), intent(in) :: name
00409     !> Name that we do have.
00410     character(len=*), intent(in) :: read_name
00411     
00412     integer name_len, read_name_len
00413 
00414     if (name /= read_name) then
00415        call spec_file_die_msg(683719069, file, &
00416             'line must begin with: ' // trim(name) &
00417             // ' not: ' // trim(read_name))
00418     end if
00419     
00420   end subroutine spec_file_check_name
00421   
00422 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00423 
00424   !> Check that the length of the line data is as given.
00425   subroutine spec_file_check_line_length(file, line, length)
00426 
00427     !> Spec file.
00428     type(spec_file_t), intent(in) :: file
00429     !> Spec line.
00430     type(spec_line_t), intent(in) :: line
00431     !> Expected data length.
00432     integer, intent(in) :: length
00433 
00434     if (size(line%data) /= length) then
00435        call spec_file_die_msg(189339129, file, 'expected ' &
00436             // trim(integer_to_string(length)) // ' data items on line')
00437     end if
00438 
00439   end subroutine spec_file_check_line_length
00440   
00441 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00442 
00443   !> Check the IOSTAT and error if it is bad.
00444   subroutine spec_file_check_read_iostat(file, ios, type)
00445 
00446     !> Spec file.
00447     type(spec_file_t), intent(in) :: file
00448     !> Iostat result.
00449     integer, intent(in) :: ios
00450     !> Type being read during error.
00451     character(len=*), intent(in) :: type
00452 
00453     if (ios /= 0) then
00454        call spec_file_die_msg(704342497, file, &
00455             'error reading: IOSTAT = ' // trim(integer_to_string(ios)))
00456     end if
00457 
00458   end subroutine spec_file_check_read_iostat
00459 
00460 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00461 
00462   !> Convert a string to an integer.
00463   integer function spec_file_string_to_integer(file, string)
00464 
00465     !> Spec file.
00466     type(spec_file_t), intent(in) :: file
00467     !> String to convert.
00468     character(len=*), intent(in) :: string
00469     
00470     integer :: val
00471     integer :: ios
00472 
00473     read(string, '(i20)', iostat=ios) val
00474     call spec_file_check_read_iostat(file, ios, "integer")
00475     spec_file_string_to_integer = val
00476 
00477   end function spec_file_string_to_integer
00478 
00479 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00480 
00481   !> Convert a string to an real.
00482   real(kind=dp) function spec_file_string_to_real(file, string)
00483 
00484     !> Spec file.
00485     type(spec_file_t), intent(in) :: file
00486     !> String to convert.
00487     character(len=*), intent(in) :: string
00488     
00489     real(kind=dp) :: val
00490     integer :: ios
00491 
00492     read(string, '(f30.0)', iostat=ios) val
00493     call spec_file_check_read_iostat(file, ios, "real")
00494     spec_file_string_to_real = val
00495 
00496   end function spec_file_string_to_real
00497 
00498 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00499 
00500   !> Convert a string to an logical.
00501   logical function spec_file_string_to_logical(file, string)
00502 
00503     !> Spec file.
00504     type(spec_file_t), intent(in) :: file
00505     !> String to convert.
00506     character(len=*), intent(in) :: string
00507     
00508     logical :: val
00509     integer :: ios
00510 
00511     val = .false.
00512     if ((trim(string) == 'yes') &
00513          .or. (trim(string) == 'y') &
00514          .or. (trim(string) == 'true') &
00515          .or. (trim(string) == 't') &
00516          .or. (trim(string) == '1')) then
00517        val = .true.
00518     elseif ((trim(string) == 'no') &
00519          .or. (trim(string) == 'n') &
00520          .or. (trim(string) == 'false') &
00521          .or. (trim(string) == 'f') &
00522          .or. (trim(string) == '0')) then
00523        val = .false.
00524     else
00525        call spec_file_check_read_iostat(file, 1, "logical")
00526     end if
00527     spec_file_string_to_logical = val
00528 
00529   end function spec_file_string_to_logical
00530 
00531 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00532 
00533   !> Read an integer from a spec file that must have the given name.
00534   subroutine spec_file_read_integer(file, name, var)
00535 
00536     !> Spec file.
00537     type(spec_file_t), intent(inout) :: file
00538     !> Name.
00539     character(len=*), intent(in) :: name
00540     !> Variable to store data.
00541     integer, intent(out) :: var
00542 
00543     type(spec_line_t) :: line
00544 
00545     call spec_line_allocate(line)
00546     call spec_file_read_line_no_eof(file, line)
00547     call spec_file_check_line_name(file, line, name)
00548     call spec_file_check_line_length(file, line, 1)
00549     var = spec_file_string_to_integer(file, line%data(1))
00550     call spec_line_deallocate(line)
00551 
00552   end subroutine spec_file_read_integer
00553   
00554 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00555 
00556   !> Read a real number from a spec file that must have the given
00557   !> name.
00558   subroutine spec_file_read_real(file, name, var)
00559 
00560     !> Spec file.
00561     type(spec_file_t), intent(inout) :: file
00562     !> Name.
00563     character(len=*), intent(in) :: name
00564     !> Variable to store data.
00565     real(kind=dp), intent(out) :: var
00566 
00567     type(spec_line_t) :: line
00568 
00569     call spec_line_allocate(line)
00570     call spec_file_read_line_no_eof(file, line)
00571     call spec_file_check_line_name(file, line, name)
00572     call spec_file_check_line_length(file, line, 1)
00573     var = spec_file_string_to_real(file, line%data(1))
00574     call spec_line_deallocate(line)
00575 
00576   end subroutine spec_file_read_real
00577 
00578 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00579 
00580   !> Read a logical from a spec file that must have a given name.
00581   subroutine spec_file_read_logical(file, name, var)
00582 
00583     !> Spec file.
00584     type(spec_file_t), intent(inout) :: file
00585     !> Name.
00586     character(len=*), intent(in) :: name
00587     !> Variable to store data.
00588     logical, intent(out) :: var
00589 
00590     type(spec_line_t) :: line
00591 
00592     call spec_line_allocate(line)
00593     call spec_file_read_line_no_eof(file, line)
00594     call spec_file_check_line_name(file, line, name)
00595     call spec_file_check_line_length(file, line, 1)
00596     var = spec_file_string_to_logical(file, line%data(1))
00597     call spec_line_deallocate(line)
00598 
00599   end subroutine spec_file_read_logical
00600 
00601 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00602 
00603   !> Read a string from a spec file that must have a given name.
00604   subroutine spec_file_read_string(file, name, var)
00605 
00606     !> Spec file.
00607     type(spec_file_t), intent(inout) :: file
00608     !> Name.
00609     character(len=*), intent(in) :: name
00610     !> Variable to store data.
00611     character(len=*), intent(out) :: var
00612 
00613     type(spec_line_t) :: line
00614 
00615     call spec_line_allocate(line)
00616     call spec_file_read_line_no_eof(file, line)
00617     call spec_file_check_line_name(file, line, name)
00618     call spec_file_check_line_length(file, line, 1)
00619     var = line%data(1)
00620     call spec_line_deallocate(line)
00621 
00622   end subroutine spec_file_read_string
00623 
00624 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00625 
00626   !> Read a complex number from a spec file that must have the given
00627   !> name.
00628   subroutine spec_file_read_complex(file, name, var)
00629 
00630     !> Spec file.
00631     type(spec_file_t), intent(inout) :: file
00632     !> Name.
00633     character(len=*), intent(in) :: name
00634     !> Variable to store data.
00635     complex(kind=dc), intent(out) :: var
00636 
00637     type(spec_line_t) :: line
00638 
00639     call spec_line_allocate(line)
00640     call spec_file_read_line_no_eof(file, line)
00641     call spec_file_check_line_name(file, line, name)
00642     call spec_file_check_line_length(file, line, 2)
00643     var = cmplx(spec_file_string_to_real(file, line%data(1)), &
00644          spec_file_string_to_real(file, line%data(2)), kind=dc)
00645     call spec_line_deallocate(line)
00646 
00647   end subroutine spec_file_read_complex
00648 
00649 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00650 
00651   !> Read an array of named lines with real data. All lines must have
00652   !> the same number of data elements.
00653   subroutine spec_file_read_real_named_array(file, max_lines, names, vals)
00654 
00655     !> Spec file.
00656     type(spec_file_t), intent(inout) :: file
00657     !> Max lines to read (0 = no max).
00658     integer, intent(in) :: max_lines
00659     !> Names of lines.
00660     character(len=SPEC_LINE_MAX_VAR_LEN), pointer :: names(:)
00661     !> Data values.
00662     real(kind=dp), pointer :: vals(:,:)
00663 
00664     type(spec_line_t), pointer :: line_array(:)
00665     integer :: num_lines, line_length, i, j
00666 
00667     allocate(line_array(0))
00668     call spec_file_read_line_array(file, max_lines, line_array)
00669     num_lines = size(line_array)
00670     deallocate(names)
00671     deallocate(vals)
00672     if (num_lines > 0) then
00673        line_length = size(line_array(1)%data)
00674        allocate(names(num_lines))
00675        allocate(vals(num_lines, line_length))
00676        do i = 1,num_lines
00677           names(i) = line_array(i)%name
00678           do j = 1,line_length
00679              vals(i,j) = spec_file_string_to_real(file, line_array(i)%data(j))
00680           end do
00681        end do
00682     else
00683        allocate(names(0))
00684        allocate(vals(0,0))
00685     end if
00686     do i = 1,num_lines
00687        call spec_line_deallocate(line_array(i))
00688     end do
00689     deallocate(line_array)
00690 
00691   end subroutine spec_file_read_real_named_array
00692 
00693 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00694 
00695   !> Read an a time-indexed array of real data.
00696   subroutine spec_file_read_timed_real_array(file, name, times, vals)
00697 
00698     !> Spec file.
00699     type(spec_file_t), intent(inout) :: file
00700     !> Variable name.
00701     character(len=*), intent(in) :: name
00702     !> Names of lines.
00703     real(kind=dp), pointer :: times(:)
00704     !> Data values.
00705     real(kind=dp), pointer :: vals(:)
00706     
00707     integer :: n_lines, n_times
00708     character(len=SPEC_LINE_MAX_VAR_LEN), pointer :: read_names(:)
00709     real(kind=dp), pointer :: read_data(:,:)
00710 
00711     allocate(read_names(0))
00712     allocate(read_data(0,0))
00713     call spec_file_read_real_named_array(file, 0, read_names, read_data)
00714 
00715     n_lines = size(read_names)
00716     if (n_lines /= 2) then
00717        call die_msg(694159200, 'must have exactly two data lines in file ' &
00718             // trim(file%name))
00719     end if
00720     n_times = size(read_data,2)
00721     if (n_times < 1) then
00722        call die_msg(925956383, 'must have at least one data poin in file ' &
00723             // trim(file%name))
00724     end if
00725     if (trim(read_names(1)) /= "time") then
00726        call die_msg(692842968, 'first data line in ' // trim(file%name) &
00727             // ' must start with: time not: ' // trim(read_names(1)))
00728     end if
00729     if (trim(read_names(2)) /= name) then
00730        call die_msg(692842968, 'second data line in ' // trim(file%name) &
00731             // ' must start with: ' // trim(name) &
00732             // ' not: ' // trim(read_names(2)))
00733     end if
00734 
00735     deallocate(times)
00736     deallocate(vals)
00737     allocate(times(n_times))
00738     allocate(vals(n_times))
00739     times = read_data(1,:)
00740     vals = read_data(2,:)
00741     deallocate(read_names)
00742     deallocate(read_data)
00743 
00744   end subroutine spec_file_read_timed_real_array
00745 
00746 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00747 
00748 end module pmc_spec_file