PartMC
2.2.1
|
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 spec_file_assert_msg(code, file, .false., msg) 00083 00084 end subroutine spec_file_die_msg 00085 00086 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00087 00088 !> Exit with an error message containing filename and line number 00089 !> if \c condition_ok is \c .false. 00090 subroutine spec_file_assert_msg(code, file, condition_ok, msg) 00091 00092 !> Failure status code. 00093 integer, intent(in) :: code 00094 !> Spec file. 00095 type(spec_file_t), intent(in) :: file 00096 !> Whether the assertion is ok. 00097 logical, intent(in) :: condition_ok 00098 !> Error message. 00099 character(len=*), intent(in) :: msg 00100 00101 if (.not. condition_ok) then 00102 call die_msg(code, "file " // trim(file%name) // " line " & 00103 // trim(integer_to_string(file%line_num)) // ": " // trim(msg)) 00104 end if 00105 00106 end subroutine spec_file_assert_msg 00107 00108 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00109 00110 !> Open a spec file for reading. 00111 subroutine spec_file_open(filename, file) 00112 00113 !> Name of file to open. 00114 character(len=*), intent(in) :: filename 00115 !> Spec file. 00116 type(spec_file_t), intent(out) :: file 00117 00118 integer :: ios, unit 00119 00120 file%name = trim(filename) 00121 file%unit = get_unit() 00122 open(unit=file%unit, status='old', file=file%name, iostat=ios) 00123 if (ios /= 0) then 00124 call die_msg(173932734, "unable to open file " // trim(file%name) & 00125 // " for reading: IOSTAT = " // trim(integer_to_string(ios))) 00126 end if 00127 file%line_num = 0 00128 00129 end subroutine spec_file_open 00130 00131 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00132 00133 !> Close a spec file. 00134 subroutine spec_file_close(file) 00135 00136 !> Spec file. 00137 type(spec_file_t), intent(in) :: file 00138 00139 close(file%unit) 00140 call free_unit(file%unit) 00141 00142 end subroutine spec_file_close 00143 00144 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00145 00146 !> Read a single line from a spec file, signaling if we have hit EOF. 00147 subroutine spec_file_read_line_raw(file, line, eof) 00148 00149 !> Spec file. 00150 type(spec_file_t), intent(inout) :: file 00151 !> Complete line read. 00152 character(len=*), intent(out) :: line 00153 !> True if at EOF. 00154 logical, intent(out) :: eof 00155 00156 integer :: ios, n_read 00157 00158 file%line_num = file%line_num + 1 00159 eof = .false. 00160 line = "" ! needed for pgf95 for reading blank lines 00161 read(unit=file%unit, fmt='(a)', advance='no', end=100, eor=110, & 00162 iostat=ios) line 00163 if (ios /= 0) then 00164 call spec_file_die_msg(869855853, file, & 00165 'error reading: IOSTAT = ' // trim(integer_to_string(ios))) 00166 end if 00167 ! only reach here if we didn't hit end-of-record (end-of-line) in 00168 ! the above read, meaning the line was too long 00169 call spec_file_die_msg(468785871, file, & 00170 'line exceeds length: ' // trim(integer_to_string(len(line)))) 00171 00172 100 line = "" ! goto here if end-of-file was encountered immediately 00173 eof = .true. 00174 00175 110 return ! goto here if end-of-record, meaning everything is ok 00176 00177 end subroutine spec_file_read_line_raw 00178 00179 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00180 00181 !> Read the next line from the spec file that contains useful data 00182 !> (stripping comments and blank lines). 00183 subroutine spec_file_read_next_data_line(file, line, eof) 00184 00185 !> Spec file. 00186 type(spec_file_t), intent(inout) :: file 00187 !> Complete line read. 00188 character(len=*), intent(out) :: line 00189 !> True if EOF encountered. 00190 logical, intent(out) :: eof 00191 00192 logical :: done 00193 00194 done = .false. 00195 do while (.not. done) 00196 call spec_file_read_line_raw(file, line, eof) 00197 if (eof) then 00198 done = .true. 00199 else 00200 call spec_line_strip_comment(line) 00201 call spec_line_tabs_to_spaces(line) 00202 call spec_line_strip_leading_spaces(line) 00203 if (len_trim(line) > 0) then 00204 done = .true. 00205 end if 00206 end if 00207 end do 00208 00209 end subroutine spec_file_read_next_data_line 00210 00211 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00212 00213 !> Read a spec_line from the spec_file. 00214 subroutine spec_file_read_line(file, line, eof) 00215 00216 !> Spec file. 00217 type(spec_file_t), intent(inout) :: file 00218 !> Spec line. 00219 type(spec_line_t), intent(inout) :: line 00220 !> True if EOF encountered. 00221 logical, intent(out) :: eof 00222 00223 character(len=SPEC_LINE_MAX_LEN) :: line_string, rest 00224 integer i, n_data 00225 logical done 00226 00227 call spec_file_read_next_data_line(file, line_string, eof) 00228 if (eof) return 00229 00230 ! strip off the name 00231 i = index(line_string, ' ') ! first space 00232 if (i == 0) then 00233 call spec_file_die_msg(117442928, file, 'line contains no whitespace') 00234 end if 00235 if (i == 1) then 00236 call spec_file_die_msg(650916702, file, 'line starts with whitespace') 00237 end if 00238 if (i >= SPEC_LINE_MAX_VAR_LEN) then 00239 call spec_file_die_msg(170403881, file, 'line name longer than: ' & 00240 // trim(integer_to_string(SPEC_LINE_MAX_VAR_LEN))) 00241 end if 00242 line%name = line_string(1:(i-1)) 00243 line_string = line_string(i:) 00244 call spec_line_strip_leading_spaces(line_string) 00245 00246 ! figure out how many data items we have (consecutive non-spaces) 00247 n_data = 0 00248 rest = line_string 00249 done = .false. 00250 do while (.not. done) 00251 if (len_trim(rest) == 0) then ! only spaces left 00252 done = .true. 00253 else 00254 ! strip the data element 00255 n_data = n_data + 1 00256 i = index(rest, ' ') ! first space 00257 rest = rest(i:) 00258 call spec_line_strip_leading_spaces(rest) 00259 end if 00260 end do 00261 00262 ! allocate the data and read out the data items 00263 call spec_line_deallocate(line) 00264 call spec_line_allocate_size(line, n_data) 00265 n_data = 0 00266 rest = line_string 00267 done = .false. 00268 do while (.not. done) 00269 if (len_trim(rest) == 0) then ! only spaces left 00270 done = .true. 00271 else 00272 ! strip the data element 00273 n_data = n_data + 1 00274 i = index(rest, ' ') ! first space 00275 if (i <= 1) then 00276 call spec_file_die_msg(332939443, file, & 00277 'internal processing error') 00278 end if 00279 if (i >= SPEC_LINE_MAX_VAR_LEN) then 00280 call spec_file_die_msg(145508629, file, & 00281 'data element ' // trim(integer_to_string(n_data)) & 00282 // ' longer than: ' & 00283 // trim(integer_to_string(SPEC_LINE_MAX_VAR_LEN))) 00284 end if 00285 line%data(n_data) = rest(1:(i-1)) 00286 rest = rest(i:) 00287 call spec_line_strip_leading_spaces(rest) 00288 end if 00289 end do 00290 00291 end subroutine spec_file_read_line 00292 00293 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00294 00295 !> Read a spec_line from the spec_file. This will always succeed or 00296 !> error out, so should only be called if we know there should be a 00297 !> valid line coming. 00298 subroutine spec_file_read_line_no_eof(file, line) 00299 00300 !> Spec file. 00301 type(spec_file_t), intent(inout) :: file 00302 !> Spec line. 00303 type(spec_line_t), intent(inout) :: line 00304 00305 logical :: eof 00306 00307 call spec_file_read_line(file, line, eof) 00308 if (eof) then 00309 call spec_file_die_msg(358475502, file, 'unexpected end of file') 00310 end if 00311 00312 end subroutine spec_file_read_line_no_eof 00313 00314 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00315 00316 !> Read a list of spec_lines from a file, stopping at max_lines 00317 !> or EOF, whichever comes first. 00318 subroutine spec_file_read_line_list(file, max_lines, line_list) 00319 00320 !> Spec file. 00321 type(spec_file_t), intent(inout) :: file 00322 !> Max lines to read (0 = no max). 00323 integer, intent(in) :: max_lines 00324 !> List of spec_lines. 00325 type(spec_line_t), pointer :: line_list(:) 00326 00327 logical :: eof 00328 integer :: i, num_lines 00329 type(spec_line_t) :: temp_line_list(SPEC_FILE_MAX_LIST_LINES) 00330 00331 ! read file, working out how many lines we have 00332 num_lines = 0 00333 eof = .false. 00334 call spec_line_allocate(temp_line_list(num_lines + 1)) 00335 call spec_file_read_line(file, temp_line_list(num_lines + 1), eof) 00336 if (eof) then 00337 call spec_line_deallocate(temp_line_list(num_lines + 1)) 00338 end if 00339 do while (.not. eof) 00340 num_lines = num_lines + 1 00341 if (num_lines > SPEC_FILE_MAX_LIST_LINES) then 00342 call spec_file_die_msg(450564159, file, & 00343 'maximum number of lines exceeded') 00344 end if 00345 if (max_lines > 0) then 00346 if (num_lines >= max_lines) then 00347 eof = .true. 00348 end if 00349 end if 00350 if (.not. eof) then 00351 call spec_line_allocate(temp_line_list(num_lines + 1)) 00352 call spec_file_read_line(file, temp_line_list(num_lines + 1), eof) 00353 if (eof) then 00354 call spec_line_deallocate(temp_line_list(num_lines + 1)) 00355 end if 00356 end if 00357 end do 00358 00359 ! copy data to actual list 00360 do i = 1,size(line_list) 00361 call spec_line_deallocate(line_list(i)) 00362 end do 00363 deallocate(line_list) 00364 allocate(line_list(num_lines)) 00365 do i = 1,num_lines 00366 call spec_line_allocate(line_list(i)) 00367 call spec_line_copy(temp_line_list(i), line_list(i)) 00368 call spec_line_deallocate(temp_line_list(i)) 00369 end do 00370 00371 end subroutine spec_file_read_line_list 00372 00373 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00374 00375 !> Read an array of spec_lines from a file, stopping at max_lines 00376 !> or EOF. All lines must have the same number of elements. 00377 subroutine spec_file_read_line_array(file, max_lines, line_array) 00378 00379 !> Spec file. 00380 type(spec_file_t), intent(inout) :: file 00381 !> Max lines to read (0 = no max). 00382 integer, intent(in) :: max_lines 00383 !> Array of spec_lines,. 00384 type(spec_line_t), pointer :: line_array(:) 00385 00386 integer :: i, line_length 00387 00388 call spec_file_read_line_list(file, max_lines, line_array) 00389 if (size(line_array) > 0) then 00390 line_length = size(line_array(1)%data) 00391 do i = 2,size(line_array) 00392 if (size(line_array(i)%data) /= line_length) then 00393 call spec_file_die_msg(298076484, file, & 00394 'lines have unequal numbers of entries for array') 00395 end if 00396 end do 00397 end if 00398 00399 end subroutine spec_file_read_line_array 00400 00401 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00402 00403 !> Check that the name of the line data is as given. 00404 subroutine spec_file_check_line_name(file, line, name) 00405 00406 !> Spec file. 00407 type(spec_file_t), intent(in) :: file 00408 !> Spec line. 00409 type(spec_line_t), intent(in) :: line 00410 !> Expected line name. 00411 character(len=*), intent(in) :: name 00412 00413 if (line%name /= name) then 00414 call spec_file_die_msg(462932478, file, & 00415 'line must begin with: ' // trim(name) & 00416 // ' not: ' // trim(line%name)) 00417 end if 00418 00419 end subroutine spec_file_check_line_name 00420 00421 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00422 00423 !> Checks that the read_name is the same as name. 00424 subroutine spec_file_check_name(file, name, read_name) 00425 00426 !> Spec file. 00427 type(spec_file_t), intent(inout) :: file 00428 !> Name that we should have. 00429 character(len=*), intent(in) :: name 00430 !> Name that we do have. 00431 character(len=*), intent(in) :: read_name 00432 00433 integer name_len, read_name_len 00434 00435 if (name /= read_name) then 00436 call spec_file_die_msg(683719069, file, & 00437 'line must begin with: ' // trim(name) & 00438 // ' not: ' // trim(read_name)) 00439 end if 00440 00441 end subroutine spec_file_check_name 00442 00443 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00444 00445 !> Check that the length of the line data is as given. 00446 subroutine spec_file_check_line_length(file, line, length) 00447 00448 !> Spec file. 00449 type(spec_file_t), intent(in) :: file 00450 !> Spec line. 00451 type(spec_line_t), intent(in) :: line 00452 !> Expected data length. 00453 integer, intent(in) :: length 00454 00455 if (size(line%data) /= length) then 00456 call spec_file_die_msg(189339129, file, 'expected ' & 00457 // trim(integer_to_string(length)) // ' data items on line') 00458 end if 00459 00460 end subroutine spec_file_check_line_length 00461 00462 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00463 00464 !> Check the IOSTAT and error if it is bad. 00465 subroutine spec_file_check_read_iostat(file, ios, type) 00466 00467 !> Spec file. 00468 type(spec_file_t), intent(in) :: file 00469 !> Iostat result. 00470 integer, intent(in) :: ios 00471 !> Type being read during error. 00472 character(len=*), intent(in) :: type 00473 00474 if (ios /= 0) then 00475 call spec_file_die_msg(704342497, file, & 00476 'error reading: IOSTAT = ' // trim(integer_to_string(ios))) 00477 end if 00478 00479 end subroutine spec_file_check_read_iostat 00480 00481 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00482 00483 !> Convert a string to an integer. 00484 integer function spec_file_string_to_integer(file, string) 00485 00486 !> Spec file. 00487 type(spec_file_t), intent(in) :: file 00488 !> String to convert. 00489 character(len=*), intent(in) :: string 00490 00491 integer :: val 00492 integer :: ios 00493 00494 read(string, '(i20)', iostat=ios) val 00495 call spec_file_check_read_iostat(file, ios, "integer") 00496 spec_file_string_to_integer = val 00497 00498 end function spec_file_string_to_integer 00499 00500 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00501 00502 !> Convert a string to an real. 00503 real(kind=dp) function spec_file_string_to_real(file, string) 00504 00505 !> Spec file. 00506 type(spec_file_t), intent(in) :: file 00507 !> String to convert. 00508 character(len=*), intent(in) :: string 00509 00510 real(kind=dp) :: val 00511 integer :: ios 00512 00513 read(string, '(f30.0)', iostat=ios) val 00514 call spec_file_check_read_iostat(file, ios, "real") 00515 spec_file_string_to_real = val 00516 00517 end function spec_file_string_to_real 00518 00519 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00520 00521 !> Convert a string to an logical. 00522 logical function spec_file_string_to_logical(file, string) 00523 00524 !> Spec file. 00525 type(spec_file_t), intent(in) :: file 00526 !> String to convert. 00527 character(len=*), intent(in) :: string 00528 00529 logical :: val 00530 integer :: ios 00531 00532 val = .false. 00533 if ((trim(string) == 'yes') & 00534 .or. (trim(string) == 'y') & 00535 .or. (trim(string) == 'true') & 00536 .or. (trim(string) == 't') & 00537 .or. (trim(string) == '1')) then 00538 val = .true. 00539 elseif ((trim(string) == 'no') & 00540 .or. (trim(string) == 'n') & 00541 .or. (trim(string) == 'false') & 00542 .or. (trim(string) == 'f') & 00543 .or. (trim(string) == '0')) then 00544 val = .false. 00545 else 00546 call spec_file_check_read_iostat(file, 1, "logical") 00547 end if 00548 spec_file_string_to_logical = val 00549 00550 end function spec_file_string_to_logical 00551 00552 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00553 00554 !> Read an integer from a spec file that must have the given name. 00555 subroutine spec_file_read_integer(file, name, var) 00556 00557 !> Spec file. 00558 type(spec_file_t), intent(inout) :: file 00559 !> Name. 00560 character(len=*), intent(in) :: name 00561 !> Variable to store data. 00562 integer, intent(out) :: var 00563 00564 type(spec_line_t) :: line 00565 00566 call spec_line_allocate(line) 00567 call spec_file_read_line_no_eof(file, line) 00568 call spec_file_check_line_name(file, line, name) 00569 call spec_file_check_line_length(file, line, 1) 00570 var = spec_file_string_to_integer(file, line%data(1)) 00571 call spec_line_deallocate(line) 00572 00573 end subroutine spec_file_read_integer 00574 00575 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00576 00577 !> Read a real number from a spec file that must have the given 00578 !> name. 00579 subroutine spec_file_read_real(file, name, var) 00580 00581 !> Spec file. 00582 type(spec_file_t), intent(inout) :: file 00583 !> Name. 00584 character(len=*), intent(in) :: name 00585 !> Variable to store data. 00586 real(kind=dp), intent(out) :: var 00587 00588 type(spec_line_t) :: line 00589 00590 call spec_line_allocate(line) 00591 call spec_file_read_line_no_eof(file, line) 00592 call spec_file_check_line_name(file, line, name) 00593 call spec_file_check_line_length(file, line, 1) 00594 var = spec_file_string_to_real(file, line%data(1)) 00595 call spec_line_deallocate(line) 00596 00597 end subroutine spec_file_read_real 00598 00599 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00600 00601 !> Read a logical from a spec file that must have a given name. 00602 subroutine spec_file_read_logical(file, name, var) 00603 00604 !> Spec file. 00605 type(spec_file_t), intent(inout) :: file 00606 !> Name. 00607 character(len=*), intent(in) :: name 00608 !> Variable to store data. 00609 logical, intent(out) :: var 00610 00611 type(spec_line_t) :: line 00612 00613 call spec_line_allocate(line) 00614 call spec_file_read_line_no_eof(file, line) 00615 call spec_file_check_line_name(file, line, name) 00616 call spec_file_check_line_length(file, line, 1) 00617 var = spec_file_string_to_logical(file, line%data(1)) 00618 call spec_line_deallocate(line) 00619 00620 end subroutine spec_file_read_logical 00621 00622 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00623 00624 !> Read a string from a spec file that must have a given name. 00625 subroutine spec_file_read_string(file, name, var) 00626 00627 !> Spec file. 00628 type(spec_file_t), intent(inout) :: file 00629 !> Name. 00630 character(len=*), intent(in) :: name 00631 !> Variable to store data. 00632 character(len=*), intent(out) :: var 00633 00634 type(spec_line_t) :: line 00635 00636 call spec_line_allocate(line) 00637 call spec_file_read_line_no_eof(file, line) 00638 call spec_file_check_line_name(file, line, name) 00639 call spec_file_check_line_length(file, line, 1) 00640 var = line%data(1) 00641 call spec_line_deallocate(line) 00642 00643 end subroutine spec_file_read_string 00644 00645 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00646 00647 !> Read a complex number from a spec file that must have the given 00648 !> name. 00649 subroutine spec_file_read_complex(file, name, var) 00650 00651 !> Spec file. 00652 type(spec_file_t), intent(inout) :: file 00653 !> Name. 00654 character(len=*), intent(in) :: name 00655 !> Variable to store data. 00656 complex(kind=dc), intent(out) :: var 00657 00658 type(spec_line_t) :: line 00659 00660 call spec_line_allocate(line) 00661 call spec_file_read_line_no_eof(file, line) 00662 call spec_file_check_line_name(file, line, name) 00663 call spec_file_check_line_length(file, line, 2) 00664 var = cmplx(spec_file_string_to_real(file, line%data(1)), & 00665 spec_file_string_to_real(file, line%data(2)), kind=dc) 00666 call spec_line_deallocate(line) 00667 00668 end subroutine spec_file_read_complex 00669 00670 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00671 00672 !> Read an array of named lines with real data. All lines must have 00673 !> the same number of data elements. 00674 subroutine spec_file_read_real_named_array(file, max_lines, names, vals) 00675 00676 !> Spec file. 00677 type(spec_file_t), intent(inout) :: file 00678 !> Max lines to read (0 = no max). 00679 integer, intent(in) :: max_lines 00680 !> Names of lines. 00681 character(len=SPEC_LINE_MAX_VAR_LEN), pointer :: names(:) 00682 !> Data values. 00683 real(kind=dp), pointer :: vals(:,:) 00684 00685 type(spec_line_t), pointer :: line_array(:) 00686 integer :: num_lines, line_length, i, j 00687 00688 allocate(line_array(0)) 00689 call spec_file_read_line_array(file, max_lines, line_array) 00690 num_lines = size(line_array) 00691 deallocate(names) 00692 deallocate(vals) 00693 if (num_lines > 0) then 00694 line_length = size(line_array(1)%data) 00695 allocate(names(num_lines)) 00696 allocate(vals(num_lines, line_length)) 00697 do i = 1,num_lines 00698 names(i) = line_array(i)%name 00699 do j = 1,line_length 00700 vals(i,j) = spec_file_string_to_real(file, line_array(i)%data(j)) 00701 end do 00702 end do 00703 else 00704 allocate(names(0)) 00705 allocate(vals(0,0)) 00706 end if 00707 do i = 1,num_lines 00708 call spec_line_deallocate(line_array(i)) 00709 end do 00710 deallocate(line_array) 00711 00712 end subroutine spec_file_read_real_named_array 00713 00714 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00715 00716 !> Read an a time-indexed array of real data. 00717 subroutine spec_file_read_timed_real_array(file, name, times, vals) 00718 00719 !> Spec file. 00720 type(spec_file_t), intent(inout) :: file 00721 !> Variable name. 00722 character(len=*), intent(in) :: name 00723 !> Names of lines. 00724 real(kind=dp), pointer :: times(:) 00725 !> Data values. 00726 real(kind=dp), pointer :: vals(:) 00727 00728 integer :: n_lines, n_times 00729 character(len=SPEC_LINE_MAX_VAR_LEN), pointer :: read_names(:) 00730 real(kind=dp), pointer :: read_data(:,:) 00731 00732 allocate(read_names(0)) 00733 allocate(read_data(0,0)) 00734 call spec_file_read_real_named_array(file, 0, read_names, read_data) 00735 00736 n_lines = size(read_names) 00737 if (n_lines /= 2) then 00738 call die_msg(694159200, 'must have exactly two data lines in file ' & 00739 // trim(file%name)) 00740 end if 00741 n_times = size(read_data,2) 00742 if (n_times < 1) then 00743 call die_msg(925956383, 'must have at least one data poin in file ' & 00744 // trim(file%name)) 00745 end if 00746 if (trim(read_names(1)) /= "time") then 00747 call die_msg(407039398, 'first data line in ' // trim(file%name) & 00748 // ' must start with: time not: ' // trim(read_names(1))) 00749 end if 00750 if (trim(read_names(2)) /= name) then 00751 call die_msg(692842968, 'second data line in ' // trim(file%name) & 00752 // ' must start with: ' // trim(name) & 00753 // ' not: ' // trim(read_names(2))) 00754 end if 00755 00756 deallocate(times) 00757 deallocate(vals) 00758 allocate(times(n_times)) 00759 allocate(vals(n_times)) 00760 times = read_data(1,:) 00761 vals = read_data(2,:) 00762 deallocate(read_names) 00763 deallocate(read_data) 00764 00765 end subroutine spec_file_read_timed_real_array 00766 00767 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00768 00769 end module pmc_spec_file