PartMC
2.1.5
|
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