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, &
40 io_close, &
43 iopar_read, &
55
56 integer, parameter, public :: iunit_out = 8
57 integer, parameter, public :: iunit_err = 9
58 character(len=MAX_PATH_LEN) :: work_dir
59 character(len=MAX_PATH_LEN) :: current_working_dir
60 integer(int64), save :: io_open_count
61 integer(int64), save :: io_close_count
62
63contains
64
65 ! ---------------------------------------------------------
69 subroutine io_init(defaults)
70 logical, optional, intent(in) :: defaults
71
72 character(len=MAX_PATH_LEN) :: filename
73 integer :: status
74
75 io_open_count = 0
76 io_close_count = 0
77
78 call get_environment_variable("PWD", current_working_dir, status=status)
79 if (status /= 0) then
80 write(*,'("ERROR: could not determine current working directory!")')
81 error stop -1
82 end if
83
84
85 ! cannot use push/pop before initializing io
86
87 if (present(defaults)) then
88 if (defaults) then
89 stdin = 5
90 stdout = 6
91 stderr = 0
92 work_dir = current_working_dir
93 return
94 end if
95 end if
96
97 stdin = 5
98
99 !%Variable stdout
100 !%Type string
101 !%Default "-"
102 !%Section Execution::IO
103 !%Description
104 !% The standard output by default goes to, well, to standard output. This can
105 !% be changed by setting this variable: if you give it a name (other than "-")
106 !% the output stream is printed in that file instead.
107 !%End
108 call parse_variable(global_namespace, 'stdout', '-', filename)
109 stdout = 6
110 if (trim(filename) /= '-') then
111 close(stdout)
112 open(stdout, file=filename, status='unknown')
113 show_progress_bar = .false.
114 end if
115
116 !%Variable stderr
117 !%Type string
118 !%Default "-"
119 !%Section Execution::IO
120 !%Description
121 !% The standard error by default goes to, well, to standard error. This can
122 !% be changed by setting this variable: if you give it a name (other than "-")
123 !% the output stream is printed in that file instead.
124 !%End
125 call parse_variable(global_namespace, 'stderr', '-', filename)
126 stderr = 0
127 if (trim(filename) /= '-') then
128 close(stderr)
129 open(stderr, file=filename, status='unknown')
130 end if
131
132 !%Variable WorkDir
133 !%Type string
134 !%Default "."
135 !%Section Execution::IO
136 !%Description
137 !% By default, all files are written and read from the working directory,
138 !% <i>i.e.</i> the directory from which the executable was launched, appended by the system name.
139 !% This behavior can be changed by setting this variable. If you set <tt>WorkDir</tt> to a name other than ".",
140 !% the following directories are written and read in that directory:
141 !%<ul>
142 !% <li>"casida/"</li>
143 !% <li>"em_resp_fd/"</li>
144 !% <li>"em_resp/"</li>
145 !% <li>"geom/"</li>
146 !% <li>"kdotp/"</li>
147 !% <li>"local.general"</li>
148 !% <li>"pcm/"</li>
149 !% <li>"profiling/"</li>
150 !% <li>"restart/"</li>
151 !% <li>"static/"</li>
152 !% <li>"td.general/"</li>
153 !% <li>"vdw/"</li>
154 !% <li>"vib_modes/"</li>
155 !%</ul>
156 !% Furthermore, some of the debug information (see <tt>Debug</tt>) is also written to <tt>WorkDir</tt> and
157 !% the non-absolute paths defined in <tt>OutputIterDir</tt> are relative to <tt>WorkDir</tt>.
158 !%End
159 call parse_variable(global_namespace, 'WorkDir', '.', work_dir)
160 ! ... and if necessary create workdir (will not harm if work_dir is already there)
161 if (work_dir /= '.') call loct_mkdir(trim(work_dir))
162
163 if (debug%info .or. debug%interaction_graph .or. debug%propagation_graph) then
165 end if
166
167 if (debug%trace_file) then
168 !wipe out debug trace files from previous runs to start fresh rather than appending
169 call debug_delete_trace()
170 end if
171
172 end subroutine io_init
173
174 ! ---------------------------------------------------------
175 subroutine io_end()
176
177 ! no PUSH/POP, because the POP would write to stderr after it was closed.
178
179 if (stderr /= 0) call io_close(stderr)
180 if (stdin /= 5) call io_close(stdin)
181 if (stdout /= 6) call io_close(stdout)
182
183 end subroutine io_end
184
189 ! ---------------------------------------------------------
190 character(len=MAX_PATH_LEN) function io_workdir() result (wpath)
191
192 integer :: len_work_dir
193 character :: first_char
194
195 len_work_dir = len_trim(work_dir)
196 first_char = work_dir(1:1)
197
198 select case (first_char)
199 case ('/')
200 ! absolute path: we just copy it
201 wpath = work_dir
202 case ('.')
203 if (len_work_dir>1) then
204 ! relative path of form './dir'. Strip '.' and append to cwd.
205 wpath = trim(current_working_dir) // trim(work_dir(2:len_work_dir))
206 else
207 wpath = current_working_dir
208 end if
209 case default
210 ! relative path without './'. Append to cwd with missing '/'
211 wpath = trim(current_working_dir) // "/" // trim(work_dir)
212 end select
213
214 end function io_workdir
215
216 ! ---------------------------------------------------------
221 !
222 character(len=MAX_PATH_LEN) function io_workpath(path, namespace) result(wpath)
223 character(len=*), intent(in) :: path
224 type(namespace_t), optional, intent(in) :: namespace
225
226 logical :: absolute_path
227 integer :: total_len
228
229 ! use the logical to avoid problems with the string length
230 absolute_path = .false.
231 if (len_trim(path) > 0) then
232 absolute_path = path(1:1) == '/'
233 end if
234
235 ! check that the path is not longer than the maximum allowed
236 total_len = len_trim(path)
237 if (.not. absolute_path) then
238 total_len = total_len + len_trim(work_dir) + 1
239 if (present(namespace)) then
240 if (namespace%len() > 0) total_len = total_len + namespace%len() + 1
241 end if
242 end if
243 if (total_len > max_path_len) then
244 write(stderr,"(A,I5)") "Path is longer than the maximum path length of ", max_path_len
245 write(stderr,"(A)") path
246 stop -1
247 end if
248
249 if (absolute_path) then
250 ! we do not change absolute path names
251 wpath = trim(path)
252 else
253 wpath = trim(work_dir)
254 if (present(namespace)) then
255 ! insert namespace into path
256 if (namespace%len() > 0) wpath = trim(wpath) + "/" + trim(namespace%get('/'))
257 end if
258 wpath = trim(wpath) + "/" + trim(path)
259 end if
260
261 end function io_workpath
262
263
264 ! ---------------------------------------------------------
265 subroutine io_mkdir(fname, namespace, parents)
266 character(len=*), intent(in) :: fname
267 type(namespace_t), optional, intent(in) :: namespace
268 logical, optional, intent(in) :: parents
269
270 logical :: parents_
271 integer :: last_slash, pos, length
272
273 parents_ = .false.
274 if (present(parents)) parents_ = parents
275
276 if (.not. parents_) then
277 call loct_mkdir(trim(io_workpath("", namespace=namespace)))
278 call loct_mkdir(trim(io_workpath(fname, namespace=namespace)))
279 else
280 last_slash = max(index(fname, "/", .true.), len_trim(fname))
281 pos = 1
282 length = index(fname, '/') - 1
283 do while (pos < last_slash)
284 call loct_mkdir(trim(io_workpath(fname(1:pos+length-1), namespace=namespace)))
285 pos = pos + length + 1
286 length = index(fname(pos:), "/") - 1
287 if (length < 1) length = len_trim(fname(pos:))
288 end do
289
290 end if
291
292 end subroutine io_mkdir
293
294
295 ! ---------------------------------------------------------
296 subroutine io_rm(fname, namespace)
297 character(len=*), intent(in) :: fname
298 type(namespace_t), optional, intent(in) :: namespace
299
300 call loct_rm(trim(io_workpath(fname, namespace=namespace)))
301
302 end subroutine io_rm
303
304
305 ! ---------------------------------------------------------
306 integer function io_open(file, namespace, action, status, form, position, die, recl, grp) result(iunit)
307 character(len=*), intent(in) :: file, action
308 type(namespace_t),intent(in), optional :: namespace
309 character(len=*), intent(in), optional :: status, form, position
310 logical, intent(in), optional :: die
311 integer, intent(in), optional :: recl
312 type(mpi_grp_t), intent(in), optional :: grp
313
314 character(len=20) :: status_, form_, position_
315 character(len=MAX_PATH_LEN) :: file_
316 logical :: die_
317 integer :: iostat
318 character(len=100) :: io_emsg
319 type(mpi_grp_t) :: grp_
320
321 if (present(grp)) then
322 grp_%comm = grp%comm
323 grp_%rank = grp%rank
324 grp_%size = grp%size
325 else
327 end if
328
329
330 if (grp_%is_root()) then
331
332 status_ = 'unknown'
333 if (present(status)) status_ = status
334 form_ = 'formatted'
335 if (present(form)) form_ = form
336 position_ = 'asis'
337 if (present(position)) position_ = position
338
339 die_ = optional_default(die, .true.)
340
341 file_ = io_workpath(file, namespace=namespace)
342
343 if (present(recl)) then
344 open(newunit=iunit, file=trim(file_), status=trim(status_), form=trim(form_), &
345 recl=recl, action=trim(action), position=trim(position_), iostat=iostat, iomsg=io_emsg)
346 else
347 open(newunit=iunit, file=trim(file_), status=trim(status_), form=trim(form_), &
348 action=trim(action), position=trim(position_), iostat=iostat, iomsg=io_emsg)
349 end if
350
351 io_open_count = io_open_count + 1
352
353 if (iostat /= 0) then
354 iunit = -1
355 if (die_) then
356 write(stderr, '(a,a)') '*** IO Error: ', trim(io_emsg)
357 call mpi_world%abort()
358 end if
359 end if
361 end if
362
363 if (grp_%size > 1) then
364 call grp_%bcast(iunit, 1, mpi_integer, 0)
365 end if
366
367 end function io_open
368
369
370 ! ---------------------------------------------------------
371 subroutine io_close(iunit, grp)
372 integer, intent(inout) :: iunit
373 type(mpi_grp_t), intent(in), optional :: grp
374
375 type(mpi_grp_t) :: grp_
376
377 if (present(grp)) then
378 grp_%comm = grp%comm
379 grp_%rank = grp%rank
380 grp_%size = grp%size
381 else
383 end if
384
385 if (grp_%is_root()) then
386 close(iunit)
387 io_close_count = io_close_count + 1
388 end if
389
390 iunit = -1
392 end subroutine io_close
393
394 ! ---------------------------------------------------------
395 subroutine io_dump_file(ounit, filename)
396 integer, intent(in) :: ounit
397 character(len=*), intent(in) :: filename
398
399 integer :: iunit, err
400 character(len=80) :: line
402 if (.not. mpi_world%is_root()) return
403
404 open(newunit=iunit, file=filename, iostat=err, action='read', status='old')
405
406 do while(err == 0)
407 read(iunit, fmt='(a80)', iostat=err) line
408 if (err == 0) then
409 write(ounit, '(a)') trim(line)
410 end if
411 end do
412
413 call io_close(iunit)
414
415 end subroutine io_dump_file
416
417
418 ! ---------------------------------------------------------
422 character(len=8) function io_get_extension(path) result(ext)
423 character(len = *), intent(in) :: path
424 integer :: i, j
425
426 i = index(path, ".", back = .true.)
427 j = index(path(i+1:), "/")
428 if (i == 0 .or. j /= 0) then
429 ext = ""
430 else
431 ext = path(i+1:)
432 end if
433
434 end function io_get_extension
435
436
437 ! ---------------------------------------------------------
439 subroutine io_debug_on_the_fly(namespace)
440 type(namespace_t), intent(in) :: namespace
441
442 ! only root node performs the check
443 if (mpi_world%is_root()) then
444 if (io_file_exists('enable_debug_mode', msg='Enabling DebugMode')) then
445 call debug_enable(debug)
446 ! this call does not hurt if the directory is already there
447 ! but is otherwise required
448 call io_mkdir('debug', namespace)
449 ! we have been notified by the user, so we can cleanup the file
450 call loct_rm('enable_debug_mode')
451 ! artificially increase sub stack to avoid underflow
453 end if
454
455 if (io_file_exists('disable_debug_mode', msg='Disabling DebugMode')) then
456 call debug_disable(debug)
457 ! we have been notified by the user, so we can cleanup the file
458 call loct_rm('disable_debug_mode')
459 end if
460
461 end if
462
463 end subroutine io_debug_on_the_fly
464
465
468 ! ---------------------------------------------------------
469 logical function io_file_exists(filename, msg) result(file_exists)
470 character(len=*), intent(in) :: filename
471 character(len=*), optional, intent(in) :: msg
472
473 file_exists = .false.
474 inquire(file=trim(filename), exist=file_exists)
475 if (file_exists .and. present(msg)) then
476 write(stderr, '(a)') trim(msg)
477 end if
478
479 end function io_file_exists
480
482 ! ---------------------------------------------------------
483 logical function io_dir_exists(dir, namespace)
484 character(len=*), intent(in) :: dir
485 type(namespace_t), optional, intent(in) :: namespace
486
487 io_dir_exists = loct_dir_exists(trim(io_workpath(dir, namespace)))
488
489 end function io_dir_exists
491 ! ---------------------------------------------------------
492 subroutine iopar_read(grp, iunit, lines, n_lines, ierr)
493 type(mpi_grp_t), intent(in) :: grp
494 integer, intent(in) :: iunit
495 character(len=*), intent(out) :: lines(:)
496 integer, intent(in) :: n_lines
497 integer, intent(out) :: ierr
498
499 integer :: il
500
501 assert(n_lines <= size(lines))
502
503 if (grp%is_root()) then
504 do il = 1, n_lines
505 read(iunit, '(a)', iostat=ierr) lines(il)
506 if (ierr /= 0) exit
507 end do
508 end if
509
510 call grp%bcast(ierr, 1, mpi_integer, 0)
511 call grp%bcast(lines(1), len(lines(1))*n_lines, mpi_character, 0)
512
513 end subroutine iopar_read
514
515 ! ---------------------------------------------------------
516 subroutine iopar_backspace(grp, iunit)
517 type(mpi_grp_t), intent(in) :: grp
518 integer, intent(in) :: iunit
519
520 if (grp%is_root()) then
521 backspace(iunit)
522 end if
523
524 end subroutine iopar_backspace
525
526
527 ! ---------------------------------------------------------
528 subroutine iopar_find_line(grp, iunit, line, ierr)
529 type(mpi_grp_t), intent(in) :: grp
530 integer, intent(in) :: iunit
531 character(len=*), intent(in) :: line
532 integer, intent(out) :: ierr
533
534 character(len=80) :: read_line
535
536 if (grp%is_root()) then
537 rewind(iunit)
538 do
539 read(iunit, '(a)', iostat=ierr) read_line
540 if (ierr /= 0 .or. trim(line) == trim(read_line)) exit
541 end do
542 end if
543
544 call grp%bcast(ierr, 1, mpi_integer, 0)
545
546 end subroutine iopar_find_line
547
548
549 ! ---------------------------------------------------------
550 subroutine io_skip_header(iunit)
551 integer, intent(in) :: iunit
552
553 character(len=1) :: a
554
555 rewind(iunit)
556 read(iunit,'(a)') a
557 do while(a == '#')
558 read(iunit,'(a)') a
559 end do
560 backspace(iunit)
561
562 end subroutine io_skip_header
563
564 ! ---------------------------------------------------------
565 integer(int64) pure function io_get_open_count() result(count)
566
567 count = io_open_count
568
569 end function io_get_open_count
570
571 ! ---------------------------------------------------------
572 integer(int64) pure function io_get_close_count() result(count)
573
574 count = io_close_count
575
576 end function io_get_close_count
577
578 ! ---------------------------------------------------------
579 subroutine io_incr_open_count()
580
582
583 end subroutine io_incr_open_count
584
585 ! ---------------------------------------------------------
586 subroutine io_incr_close_count()
589
590 end subroutine io_incr_close_count
591
592 ! ---------------------------------------------------------
593 subroutine io_incr_counters(iio)
594 integer, intent(in) :: iio
595
596 integer :: open_count
597
598 open_count = int(iio/100)
599 io_open_count = io_open_count + open_count
600 io_close_count = io_close_count + iio - open_count * 100
601
602 end subroutine io_incr_counters
603
604
605end module io_oct_m
606
607!! Local Variables:
608!! mode: f90
609!! coding: utf-8
610!! End:
subroutine, public debug_enable(this)
Definition: debug.F90:330
type(debug_t), save, public debug
Definition: debug.F90:158
subroutine, public debug_disable(this)
Definition: debug.F90:345
subroutine, public debug_delete_trace()
Definition: debug.F90:354
integer, public no_sub_stack
Definition: global.F90:254
integer, parameter, public max_path_len
Public types, variables and procedures.
Definition: global.F90:150
Definition: io.F90:116
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:518
integer(int64), save io_open_count
Definition: io.F90:155
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:165
subroutine, public io_close(iunit, grp)
Definition: io.F90:467
subroutine, public io_skip_header(iunit)
Definition: io.F90:646
subroutine, public io_incr_counters(iio)
Definition: io.F90:689
subroutine, public io_incr_close_count()
Definition: io.F90:682
subroutine, public io_end()
Definition: io.F90:271
subroutine, public iopar_read(grp, iunit, lines, n_lines, ierr)
Definition: io.F90:588
integer(int64) pure function, public io_get_close_count()
Definition: io.F90:668
logical function, public io_file_exists(filename, msg)
Returns true if a file with name 'filename' exists and issues a reminder.
Definition: io.F90:565
character(len=max_path_len) function, public io_workpath(path, namespace)
construct path name from given name and namespace
Definition: io.F90:318
subroutine, public io_incr_open_count()
Definition: io.F90:675
subroutine, public iopar_backspace(grp, iunit)
Definition: io.F90:612
integer(int64), save io_close_count
Definition: io.F90:156
subroutine, public io_debug_on_the_fly(namespace)
check if debug mode should be enabled or disabled on the fly
Definition: io.F90:535
subroutine, public io_rm(fname, namespace)
Definition: io.F90:392
character(len=max_path_len) function, public io_workdir()
construct working directory
Definition: io.F90:286
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:361
logical function, public io_dir_exists(dir, namespace)
Returns true if a dir with name 'dir' exists.
Definition: io.F90:579
subroutine, public iopar_find_line(grp, iunit, line, ierr)
Definition: io.F90:624
integer(int64) pure function, public io_get_open_count()
Definition: io.F90:661
subroutine, public io_dump_file(ounit, filename)
Definition: io.F90:491
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:402
System information (time, memory, sysname)
Definition: loct.F90:117
subroutine, public loct_rm(name)
Definition: loct.F90:318
subroutine, public loct_mkdir(name)
Definition: loct.F90:304
logical, public show_progress_bar
Define which routines can be seen from the outside.
Definition: loct.F90:149
logical function, public loct_dir_exists(dirname)
Definition: loct.F90:349
type(mpi_comm), parameter, public mpi_comm_undefined
used to indicate a communicator has not been initialized
Definition: mpi.F90:138
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:272
subroutine mpi_grp_init(grp, comm)
Initialize MPI group instance.
Definition: mpi.F90:310
type(namespace_t), public global_namespace
Definition: namespace.F90:134
This is defined even when running serial.
Definition: mpi.F90:144
int true(void)