Octopus
io.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module io_oct_m
22 use debug_oct_m
23 use global_oct_m
24 use loct_oct_m
25 use mpi_oct_m
27 use parser_oct_m
28
29 implicit none
30
31 private
32 public :: &
34 io_open, &
35 io_mkdir, &
36 io_rm, &
37 io_init, &
38 io_end, &
39 io_status, &
41 io_free, &
42 io_close, &
43 io_assign, &
46 iopar_read, &
57
58 integer, parameter, public :: iunit_out = 8
59 integer, parameter, public :: iunit_err = 9
60 integer, parameter :: min_lun=10, max_lun=10000
61 logical :: lun_is_free(min_lun:max_lun)
62 character(len=MAX_PATH_LEN) :: work_dir
63 integer(int64), save :: io_open_count
64 integer(int64), save :: io_close_count
65
66contains
67
68 ! ---------------------------------------------------------
72 subroutine io_init(defaults)
73 logical, optional, intent(in) :: defaults
74
75 character(len=MAX_PATH_LEN) :: filename
76
77 io_open_count = 0
78 io_close_count = 0
79
80 ! cannot use push/pop before initializing io
81
82 if (present(defaults)) then
83 if (defaults) then
84 lun_is_free(min_lun:max_lun)=.true.
85 stdin = 5
86 stdout = 6
87 stderr = 0
88 work_dir = '.'
89 return
90 end if
91 end if
92
93 lun_is_free(min_lun:max_lun)=.true.
94 stdin = 5
95
96 !%Variable stdout
97 !%Type string
98 !%Default "-"
99 !%Section Execution::IO
100 !%Description
101 !% The standard output by default goes to, well, to standard output. This can
102 !% be changed by setting this variable: if you give it a name (other than "-")
103 !% the output stream is printed in that file instead.
104 !%End
105 call parse_variable(global_namespace, 'stdout', '-', filename)
106 stdout = 6
107 if (trim(filename) /= '-') then
108 close(stdout)
109 open(stdout, file=filename, status='unknown')
110 end if
111
112 !%Variable stderr
113 !%Type string
114 !%Default "-"
115 !%Section Execution::IO
116 !%Description
117 !% The standard error by default goes to, well, to standard error. This can
118 !% be changed by setting this variable: if you give it a name (other than "-")
119 !% the output stream is printed in that file instead.
120 !%End
121 call parse_variable(global_namespace, 'stderr', '-', filename)
122 stderr = 0
123 if (trim(filename) /= '-') then
124 close(stderr)
125 open(stderr, file=filename, status='unknown')
126 end if
127
128 !%Variable WorkDir
129 !%Type string
130 !%Default "."
131 !%Section Execution::IO
132 !%Description
133 !% By default, all files are written and read from the working directory,
134 !% <i>i.e.</i> the directory from which the executable was launched. This behavior can
135 !% be changed by setting this variable. If you set <tt>WorkDir</tt> to a name other than ".",
136 !% the following directories are written and read in that directory:
137 !%<ul>
138 !% <li>"casida/"</li>
139 !% <li>"em_resp_fd/"</li>
140 !% <li>"em_resp/"</li>
141 !% <li>"geom/"</li>
142 !% <li>"kdotp/"</li>
143 !% <li>"local.general"</li>
144 !% <li>"pcm/"</li>
145 !% <li>"profiling/"</li>
146 !% <li>"restart/"</li>
147 !% <li>"static/"</li>
148 !% <li>"td.general/"</li>
149 !% <li>"vdw/"</li>
150 !% <li>"vib_modes/"</li>
151 !%</ul>
152 !% Furthermore, some of the debug information (see <tt>Debug</tt>) is also written to <tt>WorkDir</tt> and
153 !% the non-absolute paths defined in <tt>OutputIterDir</tt> are relative to <tt>WorkDir</tt>.
154 !%End
155 call parse_variable(global_namespace, 'WorkDir', '.', work_dir)
156 ! ... and if necessary create workdir (will not harm if work_dir is already there)
157 if (work_dir /= '.') call loct_mkdir(trim(work_dir))
158
159 if (debug%info .or. debug%interaction_graph .or. debug%propagation_graph) then
160 call io_mkdir('debug', global_namespace)
161 end if
162
163 if (debug%trace_file) then
164 !wipe out debug trace files from previous runs to start fresh rather than appending
166 end if
167
168 end subroutine io_init
169
170 ! ---------------------------------------------------------
171 subroutine io_end()
172
173 ! no PUSH/POP, because the POP would write to stderr after it was closed.
174
175 if (stderr /= 0) call io_close(stderr)
176 if (stdin /= 5) call io_close(stdin)
177 if (stdout /= 6) call io_close(stdout)
178
179 end subroutine io_end
180
181
182 ! ---------------------------------------------------------
183 subroutine io_assign(got_lun)
184 integer, intent(out) :: got_lun
185
186 integer :: iostat, lun
187 logical :: used
188
189 got_lun = -1
190
191 ! Looks for a free unit and assigns it to lun
192 do lun = min_lun, max_lun
193 if (lun_is_free(lun)) then
194 inquire(unit=lun, opened=used, iostat=iostat)
195
196 if (iostat /= 0) used = .true.
197 lun_is_free(lun) = .false.
198 if (.not. used) then
199 got_lun = lun
200 exit
201 end if
202 end if
203 end do
204
205 end subroutine io_assign
206
207
208 ! ---------------------------------------------------------
209 subroutine io_free(lun)
210 integer, intent(in) :: lun
211
212 if (lun >= min_lun .and. lun <= max_lun) &
213 lun_is_free(lun) = .true.
214
215 end subroutine io_free
216
217
218 ! ---------------------------------------------------------
219 character(len=MAX_PATH_LEN) function io_workpath(path, namespace) result(wpath)
220 character(len=*), intent(in) :: path
221 type(namespace_t), optional, intent(in) :: namespace
222
223 logical :: absolute_path
224 integer :: total_len
225
226 ! use the logical to avoid problems with the string length
227 absolute_path = .false.
228 if (len_trim(path) > 0) then
229 absolute_path = path(1:1) == '/'
230 end if
231
232 ! check that the path is not longer than the maximum allowed
233 total_len = len_trim(path)
234 if (.not. absolute_path) then
235 total_len = total_len + len_trim(work_dir) + 1
236 if (present(namespace)) then
237 if (namespace%len() > 0) total_len = total_len + namespace%len() + 1
238 end if
239 end if
240 if (total_len > max_path_len) then
241 write(stderr,"(A,I5)") "Path is longer than the maximum path length of ", max_path_len
242 end if
243
244 if (absolute_path) then
245 ! we do not change absolute path names
246 wpath = trim(path)
247 else
248 wpath = trim(work_dir)
249 if (present(namespace)) then
250 ! insert namespace into path
251 if (namespace%len() > 0) wpath = trim(wpath) + "/" + trim(namespace%get('/'))
252 end if
253 wpath = trim(wpath) + "/" + trim(path)
254 end if
255
256 end function io_workpath
257
258
259 ! ---------------------------------------------------------
260 subroutine io_mkdir(fname, namespace, parents)
261 character(len=*), intent(in) :: fname
262 type(namespace_t), optional, intent(in) :: namespace
263 logical, optional, intent(in) :: parents
265 logical :: parents_
266 integer :: last_slash, pos, length
267
268 parents_ = .false.
269 if (present(parents)) parents_ = parents
270
271 if (.not. parents_) then
272 call loct_mkdir(trim(io_workpath("", namespace=namespace)))
273 call loct_mkdir(trim(io_workpath(fname, namespace=namespace)))
274 else
275 last_slash = max(index(fname, "/", .true.), len_trim(fname))
276 pos = 1
277 length = index(fname, '/') - 1
278 do while (pos < last_slash)
279 call loct_mkdir(trim(io_workpath(fname(1:pos+length-1), namespace=namespace)))
280 pos = pos + length + 1
281 length = index(fname(pos:), "/") - 1
282 if (length < 1) length = len_trim(fname(pos:))
283 end do
284
285 end if
286
287 end subroutine io_mkdir
288
289
290 ! ---------------------------------------------------------
291 subroutine io_rm(fname, namespace)
292 character(len=*), intent(in) :: fname
293 type(namespace_t), optional, intent(in) :: namespace
294
295 call loct_rm(trim(io_workpath(fname, namespace=namespace)))
296
297 end subroutine io_rm
298
299
300 ! ---------------------------------------------------------
301 integer function io_open(file, namespace, action, status, form, position, die, recl, grp) result(iunit)
302 character(len=*), intent(in) :: file, action
303 type(namespace_t),intent(in), optional :: namespace
304 character(len=*), intent(in), optional :: status, form, position
305 logical, intent(in), optional :: die
306 integer, intent(in), optional :: recl
307 type(mpi_grp_t), intent(in), optional :: grp
308
309 character(len=20) :: status_, form_, position_
310 character(len=MAX_PATH_LEN) :: file_
311 logical :: die_
312 integer :: iostat
313 character(len=100) :: io_emsg
314 type(mpi_grp_t) :: grp_
315
316 if (present(grp)) then
317 grp_%comm = grp%comm
318 grp_%rank = grp%rank
319 grp_%size = grp%size
320 else
322 end if
323
324
325 if (mpi_grp_is_root(grp_)) then
326
327 status_ = 'unknown'
328 if (present(status)) status_ = status
329 form_ = 'formatted'
330 if (present(form)) form_ = form
331 position_ = 'asis'
332 if (present(position)) position_ = position
333 die_ = .true.
334 if (present(die)) die_ = die
335
336 call io_assign(iunit)
337 if (iunit < 0) then
338 if (die_) then
339 write(stderr, '(a)') '*** IO Error: Too many files open.'
340 end if
341 return
342 end if
343
344 file_ = io_workpath(file, namespace=namespace)
345
346 if (present(recl)) then
347 open(unit=iunit, file=trim(file_), status=trim(status_), form=trim(form_), &
348 recl=recl, action=trim(action), position=trim(position_), iostat=iostat, iomsg=io_emsg)
349 else
350 open(unit=iunit, file=trim(file_), status=trim(status_), form=trim(form_), &
351 action=trim(action), position=trim(position_), iostat=iostat, iomsg=io_emsg)
352 end if
354 io_open_count = io_open_count + 1
355
356 if (iostat /= 0) then
357 call io_free(iunit)
358 iunit = -1
359 if (die_) then
360 write(stderr, '(a,a)') '*** IO Error: ', trim(io_emsg)
361 end if
362 end if
363
364 end if
365
366 if (grp_%size > 1) then
367 call grp_%bcast(iunit, 1, mpi_integer, 0)
368 end if
369
370 end function io_open
371
372
373 ! ---------------------------------------------------------
374 subroutine io_close(iunit, grp)
375 integer, intent(inout) :: iunit
376 type(mpi_grp_t), intent(in), optional :: grp
377
378 type(mpi_grp_t) :: grp_
379
380 if (present(grp)) then
381 grp_%comm = grp%comm
382 grp_%rank = grp%rank
383 grp_%size = grp%size
384 else
386 end if
387
388 if (mpi_grp_is_root(grp_)) then
389 close(iunit)
390 io_close_count = io_close_count + 1
391 call io_free(iunit)
392 end if
393
394 iunit = -1
395
396 end subroutine io_close
397
398
399 ! ---------------------------------------------------------
402 ! ---------------------------------------------------------
403 subroutine io_status(iunit)
404 integer, intent(in) :: iunit
405
406 integer :: ii, iostat
407 logical :: opened, named
408 character(len=MAX_PATH_LEN) :: filename
409 character(len=11) :: form
410
411 write(iunit, '(a)') '******** io_status ********'
412 do ii = 0, max_lun
413 inquire(ii, opened=opened, named=named, name=filename, form=form, iostat=iostat)
414 if (iostat == 0) then
415 if (opened) then
416 if (.not. named) filename = 'No name available'
417 write(iunit, '(i4,5x,a,5x,a)') ii, form, filename
418 end if
419 else
420 write(iunit, '(i4,5x,a)') ii, 'Iostat error'
421 end if
422 end do
423 write(iunit,'(a)') '******** ********'
424
425 end subroutine io_status
426
427
428 ! ---------------------------------------------------------
429 subroutine io_dump_file(ounit, filename)
430 integer, intent(in) :: ounit
431 character(len=*), intent(in) :: filename
432
433 integer :: iunit, err
434 character(len=80) :: line
435
436 if (.not. mpi_grp_is_root(mpi_world)) return
437
438 call io_assign(iunit)
439 open(unit=iunit, file=filename, iostat=err, action='read', status='old')
440
441 do while(err == 0)
442 read(iunit, fmt='(a80)', iostat=err) line
443 if (err == 0) then
444 write(ounit, '(a)') trim(line)
445 end if
446 end do
447
448 call io_close(iunit)
449
450 end subroutine io_dump_file
451
452
453 ! ---------------------------------------------------------
457 character(len=8) function io_get_extension(path) result(ext)
458 character(len = *), intent(in) :: path
459 integer :: i, j
460
461 i = index(path, ".", back = .true.)
462 j = index(path(i+1:), "/")
463 if (i == 0 .or. j /= 0) then
464 ext = ""
465 else
466 ext = path(i+1:)
467 end if
468
469 end function io_get_extension
470
471
472 ! ---------------------------------------------------------
474 subroutine io_debug_on_the_fly(namespace)
475 type(namespace_t), intent(in) :: namespace
476
477 ! only root node performs the check
478 if (mpi_grp_is_root(mpi_world)) then
479 if (io_file_exists('enable_debug_mode', msg='Enabling DebugMode')) then
480 call debug_enable(debug)
481 ! this call does not hurt if the directory is already there
482 ! but is otherwise required
483 call io_mkdir('debug', namespace)
484 ! we have been notified by the user, so we can cleanup the file
485 call loct_rm('enable_debug_mode')
486 ! artificially increase sub stack to avoid underflow
488 end if
489
490 if (io_file_exists('disable_debug_mode', msg='Disabling DebugMode')) then
491 call debug_disable(debug)
492 ! we have been notified by the user, so we can cleanup the file
493 call loct_rm('disable_debug_mode')
494 end if
495
496 end if
497
498 end subroutine io_debug_on_the_fly
499
500
503 ! ---------------------------------------------------------
504 logical function io_file_exists(filename, msg) result(file_exists)
505 character(len=*), intent(in) :: filename
506 character(len=*), optional, intent(in) :: msg
507
508 file_exists = .false.
509 inquire(file=trim(filename), exist=file_exists)
510 if (file_exists .and. present(msg)) then
511 write(stderr, '(a)') trim(msg)
512 end if
513
514 end function io_file_exists
515
517 ! ---------------------------------------------------------
518 logical function io_dir_exists(dir, namespace)
519 character(len=*), intent(in) :: dir
520 type(namespace_t), intent(in) :: namespace
521
523
524 end function io_dir_exists
525
526 ! ---------------------------------------------------------
527 subroutine iopar_read(grp, iunit, lines, n_lines, ierr)
528 type(mpi_grp_t), intent(in) :: grp
529 integer, intent(in) :: iunit
530 character(len=*), intent(out) :: lines(:)
531 integer, intent(in) :: n_lines
532 integer, intent(out) :: ierr
533
534 integer :: il
535
536 assert(n_lines <= size(lines))
537
538 if (mpi_grp_is_root(grp)) then
539 do il = 1, n_lines
540 read(iunit, '(a)', iostat=ierr) lines(il)
541 if (ierr /= 0) exit
542 end do
543 end if
544
545 call grp%bcast(ierr, 1, mpi_integer, 0)
546 call grp%bcast(lines(1), len(lines(1))*n_lines, mpi_character, 0)
547
548 end subroutine iopar_read
549
550 ! ---------------------------------------------------------
551 subroutine iopar_backspace(grp, iunit)
552 type(mpi_grp_t), intent(in) :: grp
553 integer, intent(in) :: iunit
554
555 if (mpi_grp_is_root(grp)) then
556 backspace(iunit)
557 end if
558
559 end subroutine iopar_backspace
560
561
562 ! ---------------------------------------------------------
563 subroutine iopar_find_line(grp, iunit, line, ierr)
564 type(mpi_grp_t), intent(in) :: grp
565 integer, intent(in) :: iunit
566 character(len=*), intent(in) :: line
567 integer, intent(out) :: ierr
568
569 character(len=80) :: read_line
570
571 if (mpi_grp_is_root(grp)) then
572 rewind(iunit)
573 do
574 read(iunit, '(a)', iostat=ierr) read_line
575 if (ierr /= 0 .or. trim(line) == trim(read_line)) exit
576 end do
577 end if
578
579 call grp%bcast(ierr, 1, mpi_integer, 0)
580
581 end subroutine iopar_find_line
582
583
584 ! ---------------------------------------------------------
585 subroutine io_skip_header(iunit)
586 integer, intent(in) :: iunit
587
588 character(len=1) :: a
589
590 rewind(iunit)
591 read(iunit,'(a)') a
592 do while(a == '#')
593 read(iunit,'(a)') a
594 end do
595 backspace(iunit)
596
597 end subroutine io_skip_header
598
599 ! ---------------------------------------------------------
600 integer(int64) pure function io_get_open_count() result(count)
601
602 count = io_open_count
603
604 end function io_get_open_count
605
606 ! ---------------------------------------------------------
607 integer(int64) pure function io_get_close_count() result(count)
608
609 count = io_close_count
610
612
613 ! ---------------------------------------------------------
614 subroutine io_incr_open_count()
615
617
618 end subroutine io_incr_open_count
619
620 ! ---------------------------------------------------------
621 subroutine io_incr_close_count()
622
624
625 end subroutine io_incr_close_count
626
627 ! ---------------------------------------------------------
628 subroutine io_incr_counters(iio)
629 integer, intent(in) :: iio
630
631 integer :: open_count
632
633 open_count = int(iio/100)
634 io_open_count = io_open_count + open_count
635 io_close_count = io_close_count + iio - open_count * 100
636
637 end subroutine io_incr_counters
638
639
640end module io_oct_m
641
642!! Local Variables:
643!! mode: f90
644!! coding: utf-8
645!! End:
File-handling.
Definition: loct.F90:216
subroutine, public debug_enable(this)
Definition: debug.F90:318
type(debug_t), save, public debug
Definition: debug.F90:154
subroutine, public debug_disable(this)
Definition: debug.F90:333
subroutine, public debug_delete_trace()
Definition: debug.F90:342
integer, public no_sub_stack
Definition: global.F90:239
integer, parameter, public max_path_len
Public types, variables and procedures.
Definition: global.F90:147
Definition: io.F90:114
character(len=8) function, public io_get_extension(path)
Given a path, it returns the extension (if it exists) of the file (that is, the part of the name that...
Definition: io.F90:551
integer(int64), save io_open_count
Definition: io.F90:156
subroutine, public io_init(defaults)
If the argument defaults is present and set to true, then the routine will not try to read anything f...
Definition: io.F90:166
subroutine, public io_close(iunit, grp)
Definition: io.F90:468
subroutine, public io_skip_header(iunit)
Definition: io.F90:679
subroutine, public io_incr_counters(iio)
Definition: io.F90:722
subroutine, public io_incr_close_count()
Definition: io.F90:715
subroutine, public io_end()
Definition: io.F90:265
subroutine, public iopar_read(grp, iunit, lines, n_lines, ierr)
Definition: io.F90:621
integer(int64) pure function, public io_get_close_count()
Definition: io.F90:701
logical function, public io_file_exists(filename, msg)
Returns true if a file with name 'filename' exists and issues a reminder.
Definition: io.F90:598
character(len=max_path_len) function, public io_workpath(path, namespace)
Definition: io.F90:313
subroutine, public io_incr_open_count()
Definition: io.F90:708
subroutine, public iopar_backspace(grp, iunit)
Definition: io.F90:645
integer, parameter max_lun
Definition: io.F90:153
integer(int64), save io_close_count
Definition: io.F90:157
subroutine, public io_debug_on_the_fly(namespace)
check if debug mode should be enabled or disabled on the fly
Definition: io.F90:568
subroutine, public io_rm(fname, namespace)
Definition: io.F90:385
subroutine, public io_assign(got_lun)
Definition: io.F90:277
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:354
logical function, public io_dir_exists(dir, namespace)
Returns true if a dir with name 'dir' exists.
Definition: io.F90:612
subroutine, public io_free(lun)
Definition: io.F90:303
subroutine, public iopar_find_line(grp, iunit, line, ierr)
Definition: io.F90:657
integer(int64) pure function, public io_get_open_count()
Definition: io.F90:694
subroutine, public io_dump_file(ounit, filename)
Definition: io.F90:523
subroutine, public io_status(iunit)
Prints a list of the connected logical units and the names of the associated files.
Definition: io.F90:497
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
logical function, public loct_dir_exists(dirname)
Definition: loct.F90:333
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
Definition: mpi.F90:430
type(mpi_comm), parameter, public mpi_comm_undefined
used to indicate a communicator has not been initialized
Definition: mpi.F90:136
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
subroutine mpi_grp_init(grp, comm)
Initialize MPI group instance.
Definition: mpi.F90:346
type(namespace_t), public global_namespace
Definition: namespace.F90:132
This is defined even when running serial.
Definition: mpi.F90:142
int true(void)