PartMC  2.9.0
spec_file.F90
Go to the documentation of this file.
1 ! Copyright (C) 2007-2012, 2021 Nicole Riemer and Matthew West
2 ! Licensed under the GNU General Public License version 2 or (at your
3 ! option) any later version. See the file COPYING for details.
4 
5 !> \file
6 !> The pmc_spec_file module.
7 
8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
9 
10 !> \page spec_file_format Input File Format: Spec File Format
11 !!
12 !! All PartMC input files are in a text format. Each line consists of
13 !! a <b>parameter name</b>, followed by the <b>parameter value</b>,
14 !! and an optional comment starting with the # character. Blank lines
15 !! and comment-only lines are permitted, and everything on a line
16 !! after a # is completely ignored.
17 !!
18 !! Parameter names are strings (normally lowercase) without spaces,
19 !! such as \c output_prefix or \c del_t. The case of parameter names
20 !! is significant. The order of parameters in a file is not
21 !! arbitrary. Instead, they must come in the prescribed order and
22 !! cannot be skipped or rearranged.
23 !!
24 !! The parameter types are:
25 !! - \b string: a single string without spaces (case is significant)
26 !! - \b logical: a true/false value that can be the exact values
27 !! "yes", "y", "true", "t", or "1" (for true values), or "no",
28 !! "n", "false", "f", or "0" (for false values
29 !! - \b integer: a positive or negative integer (depending on
30 !! whether PartMC was compiled as 32bit or 64bit the maximum size
31 !! will vary)
32 !! - \b real: a floating point real number in Fortran syntax,
33 !! e.g. -1.45, 5.27e10 (the available precision and range is that
34 !! of whatever double precision meant during the compilation)
35 !! - \b complex: two real numbers separated by a space, giving the
36 !! real and imaginary parts of a complex number, respectively
37 !! - <b>real array</b>: a list of real numbers separated by spaces,
38 !! giving the entries of the array
39 
40 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
41 
42 !> Reading formatted text input.
44 
45  use pmc_spec_line
46  use pmc_util
47 
48  !> Maximum number of lines in an array.
49  integer, parameter :: spec_file_max_list_lines = 1000
50 
51  !> An input file with extra data for printing messages.
52  !!
53  !! An spec_file_t is just a simple wrapper around a Fortran unit
54  !! number together with the filename and current line number. The
55  !! line number is updated manually by the various \c spec_file_*()
56  !! subroutine. To maintain its validity all file accesses must be
57  !! done via the \c spec_file_*() subroutines, and no data should be
58  !! accessed directly via \c spec_file%%unit.
60  !> Filename.
61  character(len=SPEC_LINE_MAX_VAR_LEN) :: name
62  !> Attached unit.
63  integer :: unit
64  !> Current line number.
65  integer :: line_num
66  end type spec_file_t
67 
68 contains
69 
70 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
71 
72  !> Exit with an error message containing filename and line number.
73  subroutine spec_file_die_msg(code, file, msg)
74 
75  !> Failure status code.
76  integer, intent(in) :: code
77  !> Spec file.
78  type(spec_file_t), intent(in) :: file
79  !> Error message.
80  character(len=*), intent(in) :: msg
81 
82  call spec_file_assert_msg(code, file, .false., msg)
83 
84  end subroutine spec_file_die_msg
85 
86 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
87 
88  !> Exit with an error message containing filename and line number
89  !> if \c condition_ok is \c .false.
90  subroutine spec_file_assert_msg(code, file, condition_ok, msg)
91 
92  !> Failure status code.
93  integer, intent(in) :: code
94  !> Spec file.
95  type(spec_file_t), intent(in) :: file
96  !> Whether the assertion is ok.
97  logical, intent(in) :: condition_ok
98  !> Error message.
99  character(len=*), intent(in) :: msg
100 
101  if (.not. condition_ok) then
102  call die_msg(code, "file " // trim(file%name) // " line " &
103  // trim(integer_to_string(file%line_num)) // ": " // trim(msg))
104  end if
105 
106  end subroutine spec_file_assert_msg
107 
108 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
109 
110  !> Open a spec file for reading.
111  subroutine spec_file_open(filename, file)
112 
113  !> Name of file to open.
114  character(len=*), intent(in) :: filename
115  !> Spec file.
116  type(spec_file_t), intent(out) :: file
117 
118  integer :: ios, unit
119 
120  file%name = trim(filename)
121  file%unit = get_unit()
122  open(unit=file%unit, status='old', file=file%name, iostat=ios)
123  if (ios /= 0) then
124  call die_msg(173932734, "unable to open file " // trim(file%name) &
125  // " for reading: IOSTAT = " // trim(integer_to_string(ios)))
126  end if
127  file%line_num = 0
128 
129  end subroutine spec_file_open
130 
131 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
132 
133  !> Close a spec file.
134  subroutine spec_file_close(file)
135 
136  !> Spec file.
137  type(spec_file_t), intent(in) :: file
138 
139  close(file%unit)
140  call free_unit(file%unit)
141 
142  end subroutine spec_file_close
143 
144 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
145 
146  !> Read a single line from a spec file, signaling if we have hit EOF.
147  subroutine spec_file_read_line_raw(file, line, eof)
148 
149  !> Spec file.
150  type(spec_file_t), intent(inout) :: file
151  !> Complete line read.
152  character(len=*), intent(out) :: line
153  !> True if at EOF.
154  logical, intent(out) :: eof
155 
156  integer :: ios, n_read
157 
158  file%line_num = file%line_num + 1
159  eof = .false.
160  line = "" ! needed for pgf95 for reading blank lines
161  read(unit=file%unit, fmt='(a)', advance='no', end=100, eor=110, &
162  iostat=ios) line
163  if (ios /= 0) then
164  call spec_file_die_msg(869855853, file, &
165  'error reading: IOSTAT = ' // trim(integer_to_string(ios)))
166  end if
167  ! only reach here if we didn't hit end-of-record (end-of-line) in
168  ! the above read, meaning the line was too long
169  call spec_file_die_msg(468785871, file, &
170  'line exceeds length: ' // trim(integer_to_string(len(line))))
171 
172 100 line = "" ! goto here if end-of-file was encountered immediately
173  eof = .true.
174 
175 110 return ! goto here if end-of-record, meaning everything is ok
176 
177  end subroutine spec_file_read_line_raw
178 
179 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
180 
181  !> Read the next line from the spec file that contains useful data
182  !> (stripping comments and blank lines).
183  subroutine spec_file_read_next_data_line(file, line, eof)
184 
185  !> Spec file.
186  type(spec_file_t), intent(inout) :: file
187  !> Complete line read.
188  character(len=*), intent(out) :: line
189  !> True if EOF encountered.
190  logical, intent(out) :: eof
191 
192  logical :: done
193 
194  done = .false.
195  do while (.not. done)
196  call spec_file_read_line_raw(file, line, eof)
197  if (eof) then
198  done = .true.
199  else
200  call spec_line_strip_comment(line)
201  call spec_line_tabs_to_spaces(line)
202  call spec_line_strip_leading_spaces(line)
203  if (len_trim(line) > 0) then
204  done = .true.
205  end if
206  end if
207  end do
208 
209  end subroutine spec_file_read_next_data_line
210 
211 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
212 
213  !> Read a spec_line from the spec_file.
214  subroutine spec_file_read_line(file, line, eof)
215 
216  !> Spec file.
217  type(spec_file_t), intent(inout) :: file
218  !> Spec line.
219  type(spec_line_t), intent(inout) :: line
220  !> True if EOF encountered.
221  logical, intent(out) :: eof
222 
223  character(len=SPEC_LINE_MAX_LEN) :: line_string, rest
224  integer i, n_data
225  logical done
226 
227  call spec_file_read_next_data_line(file, line_string, eof)
228  if (eof) return
229 
230  ! strip off the name
231  i = index(line_string, ' ') ! first space
232  if (i == 0) then
233  call spec_file_die_msg(117442928, file, 'line contains no whitespace')
234  end if
235  if (i == 1) then
236  call spec_file_die_msg(650916702, file, 'line starts with whitespace')
237  end if
238  if (i >= spec_line_max_var_len) then
239  call spec_file_die_msg(170403881, file, 'line name longer than: ' &
240  // trim(integer_to_string(spec_line_max_var_len)))
241  end if
242  line%name = line_string(1:(i-1))
243  line_string = line_string(i:)
244  call spec_line_strip_leading_spaces(line_string)
245 
246  ! figure out how many data items we have (consecutive non-spaces)
247  n_data = 0
248  rest = line_string
249  done = .false.
250  do while (.not. done)
251  if (len_trim(rest) == 0) then ! only spaces left
252  done = .true.
253  else
254  ! strip the data element
255  n_data = n_data + 1
256  i = index(rest, ' ') ! first space
257  rest = rest(i:)
258  call spec_line_strip_leading_spaces(rest)
259  end if
260  end do
261 
262  ! allocate the data and read out the data items
263  call spec_line_set_size(line, n_data)
264  n_data = 0
265  rest = line_string
266  done = .false.
267  do while (.not. done)
268  if (len_trim(rest) == 0) then ! only spaces left
269  done = .true.
270  else
271  ! strip the data element
272  n_data = n_data + 1
273  i = index(rest, ' ') ! first space
274  if (i <= 1) then
275  call spec_file_die_msg(332939443, file, &
276  'internal processing error')
277  end if
278  if (i >= spec_line_max_var_len) then
279  call spec_file_die_msg(145508629, file, &
280  'data element ' // trim(integer_to_string(n_data)) &
281  // ' longer than: ' &
282  // trim(integer_to_string(spec_line_max_var_len)))
283  end if
284  line%data(n_data) = rest(1:(i-1))
285  rest = rest(i:)
286  call spec_line_strip_leading_spaces(rest)
287  end if
288  end do
289 
290  end subroutine spec_file_read_line
291 
292 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
293 
294  !> Read a spec_line from the spec_file. This will always succeed or
295  !> error out, so should only be called if we know there should be a
296  !> valid line coming.
297  subroutine spec_file_read_line_no_eof(file, line)
298 
299  !> Spec file.
300  type(spec_file_t), intent(inout) :: file
301  !> Spec line.
302  type(spec_line_t), intent(inout) :: line
303 
304  logical :: eof
305 
306  call spec_file_read_line(file, line, eof)
307  if (eof) then
308  call spec_file_die_msg(358475502, file, 'unexpected end of file')
309  end if
310 
311  end subroutine spec_file_read_line_no_eof
312 
313 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
314 
315  !> Read a list of spec_lines from a file, stopping at max_lines
316  !> or EOF, whichever comes first.
317  subroutine spec_file_read_line_list(file, max_lines, line_list)
318 
319  !> Spec file.
320  type(spec_file_t), intent(inout) :: file
321  !> Max lines to read (0 = no max).
322  integer, intent(in) :: max_lines
323  !> List of spec_lines.
324  type(spec_line_t), allocatable :: line_list(:)
325 
326  logical :: eof
327  integer :: i, num_lines
328  type(spec_line_t), allocatable :: temp_line_list(:)
329 
330  ! read file, working out how many lines we have
331  num_lines = 0
332  eof = .false.
333  allocate(temp_line_list(spec_file_max_list_lines))
334  call spec_file_read_line(file, temp_line_list(num_lines + 1), eof)
335  do while (.not. eof)
336  num_lines = num_lines + 1
337  if (num_lines > spec_file_max_list_lines) then
338  call spec_file_die_msg(450564159, file, &
339  'maximum number of lines exceeded')
340  end if
341  if (max_lines > 0) then
342  if (num_lines >= max_lines) then
343  eof = .true.
344  end if
345  end if
346  if (.not. eof) then
347  call spec_file_read_line(file, temp_line_list(num_lines + 1), eof)
348  end if
349  end do
350 
351  ! copy data to actual list
352  ! FIXME: following allocate shouldn't be needed, but is on gfortran 4.6.3
353  allocate(line_list(num_lines))
354  line_list = temp_line_list(1:num_lines)
355 
356  end subroutine spec_file_read_line_list
357 
358 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
359 
360  !> Read an array of spec_lines from a file, stopping at max_lines
361  !> or EOF. All lines must have the same number of elements.
362  subroutine spec_file_read_line_array(file, max_lines, line_array)
363 
364  !> Spec file.
365  type(spec_file_t), intent(inout) :: file
366  !> Max lines to read (0 = no max).
367  integer, intent(in) :: max_lines
368  !> Array of spec_lines,.
369  type(spec_line_t), allocatable :: line_array(:)
370 
371  integer :: i, line_length
372 
373  call spec_file_read_line_list(file, max_lines, line_array)
374  if (size(line_array) > 0) then
375  line_length = size(line_array(1)%data)
376  do i = 2,size(line_array)
377  if (size(line_array(i)%data) /= line_length) then
378  call spec_file_die_msg(298076484, file, &
379  'lines have unequal numbers of entries for array')
380  end if
381  end do
382  end if
383 
384  end subroutine spec_file_read_line_array
385 
386 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
387 
388  !> Check that the name of the line data is as given.
389  subroutine spec_file_check_line_name(file, line, name)
390 
391  !> Spec file.
392  type(spec_file_t), intent(in) :: file
393  !> Spec line.
394  type(spec_line_t), intent(in) :: line
395  !> Expected line name.
396  character(len=*), intent(in) :: name
397 
398  if (line%name /= name) then
399  call spec_file_die_msg(462932478, file, &
400  'line must begin with: ' // trim(name) &
401  // ' not: ' // trim(line%name))
402  end if
403 
404  end subroutine spec_file_check_line_name
405 
406 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
407 
408  !> Checks that the read_name is the same as name.
409  subroutine spec_file_check_name(file, name, read_name)
410 
411  !> Spec file.
412  type(spec_file_t), intent(inout) :: file
413  !> Name that we should have.
414  character(len=*), intent(in) :: name
415  !> Name that we do have.
416  character(len=*), intent(in) :: read_name
417 
418  integer name_len, read_name_len
419 
420  if (name /= read_name) then
421  call spec_file_die_msg(683719069, file, &
422  'line must begin with: ' // trim(name) &
423  // ' not: ' // trim(read_name))
424  end if
425 
426  end subroutine spec_file_check_name
427 
428 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
429 
430  !> Check that the length of the line data is as given.
431  subroutine spec_file_check_line_length(file, line, length)
432 
433  !> Spec file.
434  type(spec_file_t), intent(in) :: file
435  !> Spec line.
436  type(spec_line_t), intent(in) :: line
437  !> Expected data length.
438  integer, intent(in) :: length
439 
440  if (size(line%data) /= length) then
441  call spec_file_die_msg(189339129, file, 'expected ' &
442  // trim(integer_to_string(length)) // ' data items on line')
443  end if
444 
445  end subroutine spec_file_check_line_length
446 
447 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
448 
449  !> Check the IOSTAT and error if it is bad.
450  subroutine spec_file_check_read_iostat(file, ios, type)
451 
452  !> Spec file.
453  type(spec_file_t), intent(in) :: file
454  !> Iostat result.
455  integer, intent(in) :: ios
456  !> Type being read during error.
457  character(len=*), intent(in) :: type
458 
459  if (ios /= 0) then
460  call spec_file_die_msg(704342497, file, &
461  'error reading: IOSTAT = ' // trim(integer_to_string(ios)))
462  end if
463 
464  end subroutine spec_file_check_read_iostat
465 
466 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
467 
468  !> Set the line number and file read pointer back one entry.
469  subroutine spec_file_unread_line(file)
470 
471  !> Spec file.
472  type(spec_file_t), intent(inout) :: file
473 
474  integer :: ios
475 
476  file%line_num = file%line_num - 1
477  backspace(file%unit, iostat=ios)
478  if (ios /= 0) then
479  call spec_file_die_msg(362985714, file, &
480  'error backspacing: IOSTAT = ' // trim(integer_to_string(ios)))
481  end if
482 
483  end subroutine spec_file_unread_line
484 
485 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
486 
487  !> Convert a string to an integer.
488  integer function spec_file_string_to_integer(file, string)
489 
490  !> Spec file.
491  type(spec_file_t), intent(in) :: file
492  !> String to convert.
493  character(len=*), intent(in) :: string
494 
495  integer :: val
496  integer :: ios
497 
498  read(string, '(i20)', iostat=ios) val
499  call spec_file_check_read_iostat(file, ios, "integer")
501 
502  end function spec_file_string_to_integer
503 
504 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
505 
506  !> Convert a string to an real.
507  real(kind=dp) function spec_file_string_to_real(file, string)
508 
509  !> Spec file.
510  type(spec_file_t), intent(in) :: file
511  !> String to convert.
512  character(len=*), intent(in) :: string
513 
514  real(kind=dp) :: val
515  integer :: ios
516 
517  read(string, '(f30.0)', iostat=ios) val
518  call spec_file_check_read_iostat(file, ios, "real")
520 
521  end function spec_file_string_to_real
522 
523 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
524 
525  !> Convert a string to an logical.
526  logical function spec_file_string_to_logical(file, string)
527 
528  !> Spec file.
529  type(spec_file_t), intent(in) :: file
530  !> String to convert.
531  character(len=*), intent(in) :: string
532 
533  logical :: val
534  integer :: ios
535 
536  val = .false.
537  if ((trim(string) == 'yes') &
538  .or. (trim(string) == 'y') &
539  .or. (trim(string) == 'true') &
540  .or. (trim(string) == 't') &
541  .or. (trim(string) == '1')) then
542  val = .true.
543  elseif ((trim(string) == 'no') &
544  .or. (trim(string) == 'n') &
545  .or. (trim(string) == 'false') &
546  .or. (trim(string) == 'f') &
547  .or. (trim(string) == '0')) then
548  val = .false.
549  else
550  call spec_file_check_read_iostat(file, 1, "logical")
551  end if
553 
554  end function spec_file_string_to_logical
555 
556 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
557 
558  !> Read an integer from a spec file that must have the given name.
559  subroutine spec_file_read_integer(file, name, var)
560 
561  !> Spec file.
562  type(spec_file_t), intent(inout) :: file
563  !> Name.
564  character(len=*), intent(in) :: name
565  !> Variable to store data.
566  integer, intent(out) :: var
567 
568  type(spec_line_t) :: line
569 
570  call spec_file_read_line_no_eof(file, line)
571  call spec_file_check_line_name(file, line, name)
572  call spec_file_check_line_length(file, line, 1)
573  var = spec_file_string_to_integer(file, line%data(1))
574 
575  end subroutine spec_file_read_integer
576 
577 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
578 
579  !> Read a real number from a spec file that must have the given
580  !> name.
581  subroutine spec_file_read_real(file, name, var)
582 
583  !> Spec file.
584  type(spec_file_t), intent(inout) :: file
585  !> Name.
586  character(len=*), intent(in) :: name
587  !> Variable to store data.
588  real(kind=dp), intent(out) :: var
589 
590  type(spec_line_t) :: line
591 
592  call spec_file_read_line_no_eof(file, line)
593  call spec_file_check_line_name(file, line, name)
594  call spec_file_check_line_length(file, line, 1)
595  var = spec_file_string_to_real(file, line%data(1))
596 
597  end subroutine spec_file_read_real
598 
599 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
600 
601  !> Read a logical from a spec file that must have a given name.
602  subroutine spec_file_read_logical(file, name, var)
603 
604  !> Spec file.
605  type(spec_file_t), intent(inout) :: file
606  !> Name.
607  character(len=*), intent(in) :: name
608  !> Variable to store data.
609  logical, intent(out) :: var
610 
611  type(spec_line_t) :: line
612 
613  call spec_file_read_line_no_eof(file, line)
614  call spec_file_check_line_name(file, line, name)
615  call spec_file_check_line_length(file, line, 1)
616  var = spec_file_string_to_logical(file, line%data(1))
617 
618  end subroutine spec_file_read_logical
619 
620 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
621 
622  !> Read a string from a spec file that must have a given name.
623  subroutine spec_file_read_string(file, name, var)
624 
625  !> Spec file.
626  type(spec_file_t), intent(inout) :: file
627  !> Name.
628  character(len=*), intent(in) :: name
629  !> Variable to store data.
630  character(len=*), intent(out) :: var
631 
632  type(spec_line_t) :: line
633 
634  call spec_file_read_line_no_eof(file, line)
635  call spec_file_check_line_name(file, line, name)
636  call spec_file_check_line_length(file, line, 1)
637  var = line%data(1)
638 
639  end subroutine spec_file_read_string
640 
641 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
642 
643  !> Read a complex number from a spec file that must have the given
644  !> name.
645  subroutine spec_file_read_complex(file, name, var)
646 
647  !> Spec file.
648  type(spec_file_t), intent(inout) :: file
649  !> Name.
650  character(len=*), intent(in) :: name
651  !> Variable to store data.
652  complex(kind=dc), intent(out) :: var
653 
654  type(spec_line_t) :: line
655 
656  call spec_file_read_line_no_eof(file, line)
657  call spec_file_check_line_name(file, line, name)
658  call spec_file_check_line_length(file, line, 2)
659  var = cmplx(spec_file_string_to_real(file, line%data(1)), &
660  spec_file_string_to_real(file, line%data(2)), kind=dc)
661 
662  end subroutine spec_file_read_complex
663 
664 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
665 
666  !> Read an array of named lines with real data. All lines must have
667  !> the same number of data elements.
668  subroutine spec_file_read_real_named_array(file, max_lines, names, vals)
669 
670  !> Spec file.
671  type(spec_file_t), intent(inout) :: file
672  !> Max lines to read (0 = no max).
673  integer, intent(in) :: max_lines
674  !> Names of lines.
675  character(len=SPEC_LINE_MAX_VAR_LEN), allocatable :: names(:)
676  !> Data values.
677  real(kind=dp), allocatable :: vals(:,:)
678 
679  type(spec_line_t), allocatable :: line_array(:)
680  integer :: num_lines, line_length, i, j
681 
682  call spec_file_read_line_array(file, max_lines, line_array)
683  num_lines = size(line_array)
684  if (allocated(names)) deallocate(names)
685  if (allocated(vals)) deallocate(vals)
686  if (num_lines > 0) then
687  line_length = size(line_array(1)%data)
688  allocate(names(num_lines))
689  allocate(vals(num_lines, line_length))
690  do i = 1,num_lines
691  names(i) = line_array(i)%name
692  do j = 1,line_length
693  vals(i,j) = spec_file_string_to_real(file, line_array(i)%data(j))
694  end do
695  end do
696  else
697  allocate(names(0))
698  allocate(vals(0,0))
699  end if
700 
701  end subroutine spec_file_read_real_named_array
702 
703 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
704 
705  !> Read an a time-indexed array of real data.
706  subroutine spec_file_read_timed_real_array(file, name, times, vals)
707 
708  !> Spec file.
709  type(spec_file_t), intent(inout) :: file
710  !> Variable name.
711  character(len=*), intent(in) :: name
712  !> Names of lines.
713  real(kind=dp), allocatable :: times(:)
714  !> Data values.
715  real(kind=dp), allocatable :: vals(:)
716 
717  integer :: n_lines, n_times
718  character(len=SPEC_LINE_MAX_VAR_LEN), allocatable :: read_names(:)
719  real(kind=dp), allocatable :: read_data(:,:)
720 
721  call spec_file_read_real_named_array(file, 0, read_names, read_data)
722 
723  n_lines = size(read_names)
724  if (n_lines /= 2) then
725  call die_msg(694159200, 'must have exactly two data lines in file ' &
726  // trim(file%name))
727  end if
728  n_times = size(read_data,2)
729  if (n_times < 1) then
730  call die_msg(925956383, 'must have at least one data poin in file ' &
731  // trim(file%name))
732  end if
733  if (trim(read_names(1)) /= "time") then
734  call die_msg(407039398, 'first data line in ' // trim(file%name) &
735  // ' must start with: time not: ' // trim(read_names(1)))
736  end if
737  if (trim(read_names(2)) /= name) then
738  call die_msg(692842968, 'second data line in ' // trim(file%name) &
739  // ' must start with: ' // trim(name) &
740  // ' not: ' // trim(read_names(2)))
741  end if
742 
743  times = read_data(1,:)
744  vals = read_data(2,:)
745 
746  end subroutine spec_file_read_timed_real_array
747 
748 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
749 
750 end module pmc_spec_file
pmc_spec_file::spec_file_read_line_raw
subroutine spec_file_read_line_raw(file, line, eof)
Read a single line from a spec file, signaling if we have hit EOF.
Definition: spec_file.F90:148
pmc_spec_file::spec_file_read_complex
subroutine spec_file_read_complex(file, name, var)
Read a complex number from a spec file that must have the given name.
Definition: spec_file.F90:646
pmc_spec_file::spec_file_read_integer
subroutine spec_file_read_integer(file, name, var)
Read an integer from a spec file that must have the given name.
Definition: spec_file.F90:560
pmc_spec_file::spec_file_string_to_integer
integer function spec_file_string_to_integer(file, string)
Convert a string to an integer.
Definition: spec_file.F90:489
pmc_spec_file::spec_file_close
subroutine spec_file_close(file)
Close a spec file.
Definition: spec_file.F90:135
pmc_util::get_unit
integer function get_unit()
Returns an available unit number. This should be freed by free_unit().
Definition: util.F90:149
pmc_util::die_msg
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:135
pmc_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
pmc_spec_file
Reading formatted text input.
Definition: spec_file.F90:43
pmc_spec_file::spec_file_read_logical
subroutine spec_file_read_logical(file, name, var)
Read a logical from a spec file that must have a given name.
Definition: spec_file.F90:603
pmc_spec_file::spec_file_max_list_lines
integer, parameter spec_file_max_list_lines
Maximum number of lines in an array.
Definition: spec_file.F90:49
pmc_spec_file::spec_file_t
An input file with extra data for printing messages.
Definition: spec_file.F90:59
pmc_spec_file::spec_file_read_real
subroutine spec_file_read_real(file, name, var)
Read a real number from a spec file that must have the given name.
Definition: spec_file.F90:582
pmc_util::integer_to_string
character(len=pmc_util_convert_string_len) function integer_to_string(val)
Convert an integer to a string format.
Definition: util.F90:767
pmc_spec_file::spec_file_check_name
subroutine spec_file_check_name(file, name, read_name)
Checks that the read_name is the same as name.
Definition: spec_file.F90:410
pmc_spec_file::spec_file_check_line_length
subroutine spec_file_check_line_length(file, line, length)
Check that the length of the line data is as given.
Definition: spec_file.F90:432
pmc_spec_file::spec_file_string_to_logical
logical function spec_file_string_to_logical(file, string)
Convert a string to an logical.
Definition: spec_file.F90:527
pmc_spec_file::spec_file_check_read_iostat
subroutine spec_file_check_read_iostat(file, ios, type)
Check the IOSTAT and error if it is bad.
Definition: spec_file.F90:451
pmc_spec_file::spec_file_read_line_list
subroutine spec_file_read_line_list(file, max_lines, line_list)
Read a list of spec_lines from a file, stopping at max_lines or EOF, whichever comes first.
Definition: spec_file.F90:318
pmc_spec_file::spec_file_open
subroutine spec_file_open(filename, file)
Open a spec file for reading.
Definition: spec_file.F90:112
pmc_spec_file::spec_file_read_line_array
subroutine spec_file_read_line_array(file, max_lines, line_array)
Read an array of spec_lines from a file, stopping at max_lines or EOF. All lines must have the same n...
Definition: spec_file.F90:363
pmc_spec_file::spec_file_read_timed_real_array
subroutine spec_file_read_timed_real_array(file, name, times, vals)
Read an a time-indexed array of real data.
Definition: spec_file.F90:707
pmc_spec_file::spec_file_read_line_no_eof
subroutine spec_file_read_line_no_eof(file, line)
Read a spec_line from the spec_file. This will always succeed or error out, so should only be called ...
Definition: spec_file.F90:298
pmc_spec_file::spec_file_string_to_real
real(kind=dp) function spec_file_string_to_real(file, string)
Convert a string to an real.
Definition: spec_file.F90:508
pmc_spec_file::spec_file_read_real_named_array
subroutine spec_file_read_real_named_array(file, max_lines, names, vals)
Read an array of named lines with real data. All lines must have the same number of data elements.
Definition: spec_file.F90:669
pmc_spec_file::spec_file_read_line
subroutine spec_file_read_line(file, line, eof)
Read a spec_line from the spec_file.
Definition: spec_file.F90:215
pmc_spec_file::spec_file_read_next_data_line
subroutine spec_file_read_next_data_line(file, line, eof)
Read the next line from the spec file that contains useful data (stripping comments and blank lines).
Definition: spec_file.F90:184
pmc_util
Common utility subroutines.
Definition: util.F90:9
pmc_spec_file::spec_file_unread_line
subroutine spec_file_unread_line(file)
Set the line number and file read pointer back one entry.
Definition: spec_file.F90:470
pmc_spec_file::spec_file_die_msg
subroutine spec_file_die_msg(code, file, msg)
Exit with an error message containing filename and line number.
Definition: spec_file.F90:74
pmc_spec_file::spec_file_read_string
subroutine spec_file_read_string(file, name, var)
Read a string from a spec file that must have a given name.
Definition: spec_file.F90:624
pmc_constants::dc
integer, parameter dc
Kind of a double precision complex number.
Definition: constants.F90:14
pmc_util::free_unit
subroutine free_unit(unit)
Frees a unit number returned by get_unit().
Definition: util.F90:173
pmc_spec_file::spec_file_check_line_name
subroutine spec_file_check_line_name(file, line, name)
Check that the name of the line data is as given.
Definition: spec_file.F90:390
pmc_spec_line
A single line of formatted test for input.
Definition: spec_line.F90:9
pmc_spec_file::spec_file_assert_msg
subroutine spec_file_assert_msg(code, file, condition_ok, msg)
Exit with an error message containing filename and line number if condition_ok is ....
Definition: spec_file.F90:91