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