1! 2! ~~~ BUffer Input/Output Library. ~~~ 3! Copyright Lorenzo Paulatto <paulatz@gmail.com> 2013 4! 5! Contains a few changes by PG wrt the original implementation: 6! - data is complex, not real 7! - most routines are functions that return error status instead of stopping 8! - added possibility to store file name info in the linked list 9! 10! This file is distributed under the terms of the 11! GNU General Public License. See the file `License' 12! in the root directory of the present distribution, 13! or http://www.gnu.org/copyleft/gpl.txt 14! 15! <<^V^\\=========================================//-//-//========//O\\// 16MODULE buiol 17 !! BUffer Input/Output Library 18 ! 19 USE kinds, ONLY : DP 20 ! 21 PUBLIC :: init_buiol ! init the linked chain of i/o units 22 PUBLIC :: is_init_buiol ! .t. between call to init_buiol and stop_buiol 23 PUBLIC :: stop_buiol ! destroy the linked chain, dealloc everything 24 PUBLIC :: report_buiol ! report on total number of units and memory usage 25 PUBLIC :: buiol_open_unit ! (unit, recl, ext, dir) open a new unit 26 PUBLIC :: buiol_close_unit ! (unit) close the unit, dealloc the space 27 PUBLIC :: buiol_check_unit ! (unit) returns recl, if opened, -1 if closed 28 PUBLIC :: buiol_get_ext ! (unit) returns file extension 29 PUBLIC :: buiol_get_dir ! (unit) returns dir where file is opened 30 PUBLIC :: buiol_report_unit ! (unit, mem?) report about unit status (on stdout) 31 PUBLIC :: buiol_write_record ! (unit, recl, nrec, DATA) write DATA(recl) in record nrec of unit 32 PUBLIC :: buiol_read_record ! (unit, recl, nrec, DATA) read DATA(recl) from record nrec of unit 33 ! 34 PRIVATE 35 ! 36 INTEGER,PARAMETER :: nrec0 = 1024 37 !! initial number of records in the buffer (each record will only be allocated on write!) 38 39 REAL(DP),PARAMETER :: fact0 = 1.5_dp 40 !! when writing beyond the last available record increase the index by AT LEAST this factor.. 41 42 REAL(DP),PARAMETER :: fact1 = 1.2_dp 43 !! .. furthermore, allocate up to AT LEAST this factor times the required overflowing nrec 44 ! 45 ! NOTE: the new buffer size will be determined with both methods, taking the MAX of the two 46 ! 47 INTEGER,PARAMETER :: size0 = DP ! 8 bytes 48 !! Size of the single item of the record (for memory usage report only) 49 ! 50 TYPE index_of_list 51 !! base element of the linked chain of buffers 52 TYPE(data_in_the_list),POINTER :: index(:) 53 INTEGER :: nrec, unit, recl 54 CHARACTER(LEN=256) :: extension, save_dir 55 TYPE(index_of_list),POINTER :: next => null() 56 END TYPE 57 ! 58 TYPE data_in_the_list 59 !! sub-structure containing the data buffer 60 COMPLEX(DP), POINTER :: data(:) => null() 61 END TYPE 62 ! 63 TYPE(index_of_list),SAVE,POINTER :: ENTRY => null() 64 !! beginning of the linked chain, statically allocated (for implementation simplicity) 65 ! 66 LOGICAL,SAVE :: is_init_buiol = .false. 67 !! set to true when the library has been initialized 68 ! 69 CONTAINS 70 ! <<^V^\\=========================================//-//-//========//O\\// 71 ! 72 SUBROUTINE init_buiol 73 IMPLICIT NONE 74 ! avoid initializing twice, or we will loose the head of the list! 75 IF (is_init_buiol) THEN 76#if defined(__DEBUG) 77 CALL infomsg('buiol', 'already initialized') 78#endif 79 RETURN 80 ENDIF 81 ! 82 ALLOCATE(ENTRY) 83 ALLOCATE(ENTRY%index(0)) 84 ENTRY%nrec = 0 85 ENTRY%unit = -1 86 ENTRY%recl = -1 87 ENTRY%extension= ' ' 88 ENTRY%save_dir = ' ' 89 NULLIFY(ENTRY%next) 90 is_init_buiol = .true. 91 ! 92 RETURN 93 END SUBROUTINE init_buiol 94 ! \/o\________\\\_________________________________________/^> 95 SUBROUTINE stop_buiol 96 IMPLICIT NONE 97 TYPE(index_of_list),POINTER :: CURSOR, AUX 98 IF (.not.is_init_buiol) RETURN 99 IF (.not.associated(ENTRY) ) CALL errore('stop_buiol', 'ENTRY was lost.',1) 100 ! 101 CURSOR => ENTRY 102 DO WHILE (associated(CURSOR%NEXT)) 103 AUX => CURSOR 104 CURSOR => CURSOR%NEXT 105 CALL dealloc_buffer(AUX) 106 ENDDO 107 CALL dealloc_buffer(CURSOR) 108 ! 109 is_init_buiol=.false. 110 RETURN 111 END SUBROUTINE stop_buiol 112 ! \/o\________\\\_________________________________________/^> 113 SUBROUTINE report_buiol 114 IMPLICIT NONE 115 TYPE(index_of_list),POINTER :: CURSOR 116 INTEGER :: mem 117 ! 118 IF (.not.is_init_buiol) THEN 119 WRITE(*,'(2x,a,3i14)') "[BUIOL] not even initialized" 120 RETURN 121 ENDIF 122 ! 123 WRITE(*,'(2x,106("-") )') 124 mem = 0 125 CURSOR => ENTRY 126 DO WHILE (associated(CURSOR%NEXT)) 127 CALL buiol_report_buffer(CURSOR, mem) 128 CURSOR => CURSOR%NEXT 129 ENDDO 130 CALL buiol_report_buffer(CURSOR, mem) 131 WRITE(*,'(2x,106("-"))') 132 WRITE(*,'(2x,a,3i14)') "[BUIOL] total memory used B/KB/MB", mem, mem/1024, mem/1024**2 133 WRITE(*,'(2x,106("-"))') 134 135 RETURN 136 END SUBROUTINE report_buiol 137 ! \/o\________\\\_________________________________________/^> 138 FUNCTION buiol_open_unit(unit, recl, extension, save_dir) RESULT (ierr) 139 IMPLICIT NONE 140 INTEGER,INTENT(in) :: unit, recl 141 CHARACTER(LEN=*), INTENT(in) :: extension, save_dir 142 INTEGER :: ierr 143 TYPE(index_of_list),POINTER :: CURSOR 144 ! 145 IF (.not.is_init_buiol) CALL errore('buiol_open_unit', 'You must init before open',1) 146 IF(recl<0) THEN 147#if defined(__DEBUG) 148 CALL infomsg('buiol_open_unit', 'wrong recl') 149#endif 150 ierr = 1 151 RETURN 152 END IF 153 ! 154 ! check if the unit is already opened 155 CURSOR => find_unit(unit) 156 IF(associated(CURSOR)) THEN 157#if defined(__DEBUG) 158 CALL infomsg('buiol_open_unit', 'unit already opened') 159#endif 160 ierr = -1 161 RETURN 162 END IF 163 ! 164 ! all is fine, allocate a new unit with standard size 165 CURSOR => alloc_buffer(unit, recl, nrec0, extension, save_dir) 166 ! 167 ! place it at the beginning of the chain 168 CURSOR%next => ENTRY%next 169 ENTRY%next => CURSOR 170 ierr = 0 171 ! 172 RETURN 173 ! 174 END FUNCTION buiol_open_unit 175 ! \/o\________\\\_________________________________________/^> 176 FUNCTION buiol_close_unit(unit) RESULT (ierr) 177 IMPLICIT NONE 178 INTEGER,INTENT(in) :: unit 179 INTEGER :: ierr 180 TYPE(index_of_list),POINTER :: CURSOR, AUX 181 ! 182 ! find the unit to close 183 CURSOR => find_prev_unit(unit) 184 IF(.not.associated(CURSOR)) THEN 185#if defined(__DEBUG) 186 CALL infomsg('buiol_close_unit', 'cannot close this unit') 187#endif 188 ierr = 1 189 END IF 190 IF(.not.associated(CURSOR%next)) THEN 191#if defined(__DEBUG) 192 CALL infomsg('buiol_close_unit', 'cannot find unit to close',1) 193#endif 194 ierr = 2 195 END IF 196 ! 197 ! replace this unit with the next, but keep track of it 198 AUX => CURSOR%next 199 CURSOR%next => AUX%next ! <--- works even if %next is null() 200 ! 201 ! destroy the closed unit 202 CALL dealloc_buffer(AUX) 203 ierr = 0 204 ! 205 RETURN 206 ! 207 END FUNCTION buiol_close_unit 208 ! \/o\________\\\_________________________________________/^> 209 FUNCTION buiol_check_unit(unit) RESULT(recl) 210 IMPLICIT NONE 211 INTEGER,INTENT(in) :: unit 212 INTEGER :: recl 213 TYPE(index_of_list),POINTER :: CURSOR 214 ! 215 ! find the unit 216 CURSOR => find_unit(unit) 217 IF(.not.associated(CURSOR)) THEN 218 recl = -1 219 ELSE 220 recl = CURSOR%recl 221 ENDIF 222 ! 223 RETURN 224 ! 225 END FUNCTION buiol_check_unit 226 ! \/o\________\\\_________________________________________/^> 227 FUNCTION buiol_get_ext(unit) RESULT(extension) 228 IMPLICIT NONE 229 INTEGER,INTENT(in) :: unit 230 CHARACTER(LEN=256) :: extension 231 TYPE(index_of_list),POINTER :: CURSOR 232 ! 233 ! find the unit 234 CURSOR => find_unit(unit) 235 IF(.not.associated(CURSOR)) THEN 236 extension = ' ' 237 ELSE 238 extension = CURSOR%extension 239 ENDIF 240 ! 241 RETURN 242 ! 243 END FUNCTION buiol_get_ext 244 ! \/o\________\\\_________________________________________/^> 245 FUNCTION buiol_get_dir(unit) RESULT(save_dir) 246 IMPLICIT NONE 247 INTEGER,INTENT(in) :: unit 248 CHARACTER(LEN=256) :: save_dir 249 TYPE(index_of_list),POINTER :: CURSOR 250 ! 251 ! find the unit 252 CURSOR => find_unit(unit) 253 IF(.not.associated(CURSOR)) THEN 254 save_dir = ' ' 255 ELSE 256 save_dir = CURSOR%save_dir 257 ENDIF 258 ! 259 RETURN 260 ! 261 END FUNCTION buiol_get_dir 262 ! \/o\______\\_______________________________________/^> 263 SUBROUTINE increase_nrec(nrec_new, CURSOR) 264 IMPLICIT NONE 265 INTEGER,INTENT(in) :: nrec_new 266 TYPE(index_of_list),POINTER,INTENT(inout) :: CURSOR 267 ! 268 INTEGER :: i 269 TYPE(data_in_the_list),POINTER :: new(:), old(:) 270 ! 271 IF(nrec_new < CURSOR%nrec) CALL errore('increase_nrec', 'wrong new nrec',1) 272 ! 273 ! create a new index with more space 274 ALLOCATE(new(nrec_new)) 275 ! 276 ! associate the data to the new unit 277 old => CURSOR%index 278 DO i = 1, CURSOR%nrec 279 new(i)%data => old(i)%data ! <-- also the null() are copied 280 ENDDO 281 CURSOR%index => new 282 ! 283 ! clean the old index 284 CURSOR%nrec = nrec_new 285 DEALLOCATE(old) 286 ! 287 RETURN 288 ! 289 END SUBROUTINE increase_nrec 290 ! \/o\________\\\_________________________________________/^> 291 FUNCTION buiol_write_record(unit, recl, nrec, DATA) RESULT (ierr) 292 IMPLICIT NONE 293 INTEGER,INTENT(in) :: unit, recl, nrec 294 COMPLEX(dp),INTENT(in) :: DATA(recl) 295 INTEGER :: ierr 296 ! 297 TYPE(index_of_list),POINTER :: CURSOR 298 INTEGER :: nrec_new 299 ! 300 ! find the unit, if it exists 301 CURSOR => find_unit(unit) 302 IF(.not.associated(CURSOR)) THEN 303#if defined(__DEBUG) 304 CALL infomsg('buiol_write_record', 'cannot write: unit not opened') 305#endif 306 ierr = 1 307 RETURN 308 END IF 309 IF(CURSOR%recl/=recl) THEN 310#if defined(__DEBUG) 311 CALL infomsg('buiol_write_record', 'cannot write: wrong recl') 312#endif 313 ierr = 2 314 RETURN 315 END IF 316 ! 317 ! increase size of index, if necessary 318 IF(CURSOR%nrec<nrec) THEN 319 nrec_new = NINT(MAX(fact0*DBLE(CURSOR%nrec),fact1*DBLE(nrec))) 320 CALL increase_nrec(nrec_new, CURSOR ) 321 ENDIF 322 ! 323 IF(.not.associated(CURSOR%index(nrec)%data)) & 324 ALLOCATE( CURSOR%index(nrec)%data(recl) ) 325 ! 326 ! copy the data 327 CURSOR%index(nrec)%data = DATA 328 ierr = 0 329 RETURN 330 ! 331 END FUNCTION 332 ! \/o\________\\\_________________________________________/^> 333 FUNCTION buiol_read_record(unit, recl, nrec, DATA) RESULT (ierr) 334 IMPLICIT NONE 335 INTEGER,INTENT(in) :: unit, recl, nrec 336 COMPLEX(dp),INTENT(out) :: DATA(recl) 337 INTEGER :: ierr 338 ! 339 TYPE(index_of_list),POINTER :: CURSOR 340 ! 341 ! sanity checks 342 CURSOR => find_unit(unit) 343 IF(.not.associated(CURSOR)) THEN 344#if defined(__DEBUG) 345 CALL infomsg('buiol_read_record', 'cannot read: unit not opened') 346#endif 347 ierr = 1 348 RETURN 349 END IF 350 IF(CURSOR%recl/=recl) THEN 351#if defined(__DEBUG) 352 CALL infomsg('buiol_read_record', 'cannot read: wrong recl') 353#endif 354 ierr = 1 355 RETURN 356 END IF 357 IF(CURSOR%nrec<nrec) THEN 358#if defined(__DEBUG) 359 CALL infomsg('buiol_read_record', 'cannot read: wrong nrec') 360#endif 361 ierr =-1 362 RETURN 363 END IF 364 IF(.not.associated(CURSOR%index(nrec)%data)) THEN 365#if defined(__DEBUG) 366 CALL infomsg('buiol_read_record', 'cannot read: virgin nrec') 367#endif 368 ierr =-1 369 RETURN 370 END IF 371 ! 372 DATA = CURSOR%index(nrec)%data 373 ierr = 0 374 RETURN 375 ! 376 END FUNCTION buiol_read_record 377 ! \/o\________\\\_________________________________________/^> 378 SUBROUTINE buiol_report_unit(unit) 379 IMPLICIT NONE 380 INTEGER,INTENT(in) :: unit 381 ! 382 TYPE(index_of_list),POINTER :: CURSOR 383 ! sanity checks 384 CURSOR => find_unit(unit) 385#if defined(__DEBUG) 386 IF(.not.associated(CURSOR)) CALL errore('buiol_report_unit', 'cannot report: unit not opened',1) 387#endif 388 CALL buiol_report_buffer(CURSOR) 389 RETURN 390 ! 391 END SUBROUTINE buiol_report_unit 392 ! \/o\________\\\_________________________________________/^> 393 SUBROUTINE buiol_report_buffer(CURSOR, mem) 394 IMPLICIT NONE 395 TYPE(index_of_list),INTENT(in) :: CURSOR 396 INTEGER,OPTIONAL,INTENT(inout) :: mem 397 ! 398 INTEGER :: i, ndata, bytes 399 ! 400 ndata = 0 401 DO i = 1,CURSOR%nrec 402 IF(associated(CURSOR%index(i)%data)) ndata=ndata+1 403 ENDDO 404 ! 405 bytes = ndata*CURSOR%recl*size0 406 WRITE(*,'(2x,a,2(a,i8),(a,2i8),(a,i12))') "[BUIOL] ", & 407 "unit:", CURSOR%unit, & 408 " | recl:", CURSOR%recl, & 409 " | nrec (idx/alloc):", CURSOR%nrec, ndata, & 410 " | memory used:", bytes 411 IF(present(mem)) mem = mem+bytes 412 RETURN 413 ! 414 END SUBROUTINE buiol_report_buffer 415 ! \/o\________\\\_________________________________________/^> 416 FUNCTION find_unit(unit) RESULT(CURSOR) 417 IMPLICIT NONE 418 INTEGER,INTENT(in) :: unit 419 TYPE(index_of_list),POINTER :: CURSOR 420 ! 421 IF (.not.is_init_buiol) CALL errore('find_unit', 'You must init before find_unit',1) 422 ! 423 CURSOR => ENTRY 424 DO WHILE (associated(CURSOR%NEXT)) 425 CURSOR => CURSOR%NEXT 426 IF(CURSOR%unit == unit) RETURN ! <-- found 427 ENDDO 428 CURSOR => null() ! <------------------ not found 429 RETURN 430 END FUNCTION find_unit 431 ! \/o\________\\\_________________________________________/^> 432 FUNCTION find_prev_unit(unit) RESULT(CURSOR) 433 IMPLICIT NONE 434 INTEGER,INTENT(in) :: unit 435 TYPE(index_of_list),POINTER :: CURSOR 436 ! 437 IF (.not.is_init_buiol) CALL errore('find_prev_unit', 'You must init before find_prev_unit',1) 438 ! 439 CURSOR => ENTRY 440 DO WHILE (associated(CURSOR%NEXT)) 441 IF(CURSOR%next%unit == unit) RETURN ! <-- found 442 CURSOR => CURSOR%NEXT 443 ENDDO 444 CURSOR => null() ! <------------------ not found 445 RETURN 446 END FUNCTION find_prev_unit 447 ! \/o\________\\\_________________________________________/^> 448 FUNCTION alloc_buffer(unit, recl, nrec, extension, save_dir) 449 IMPLICIT NONE 450 INTEGER,INTENT(in) :: unit, recl, nrec 451 CHARACTER(LEN=*), INTENT(in) :: extension, save_dir 452 TYPE(index_of_list),POINTER :: alloc_buffer 453 TYPE(index_of_list),POINTER :: CURSOR 454 ! 455 ALLOCATE(CURSOR) 456 CURSOR%unit = unit 457 CURSOR%recl = recl 458 CURSOR%nrec = nrec0 459 CURSOR%extension = extension 460 CURSOR%save_dir = save_dir 461 NULLIFY(CURSOR%next) 462 ALLOCATE(CURSOR%index(CURSOR%nrec)) 463 ! 464 alloc_buffer => CURSOR 465 RETURN 466 END FUNCTION alloc_buffer 467 ! \/o\________\\\_________________________________________/^> 468 SUBROUTINE dealloc_buffer(CURSOR) 469 IMPLICIT NONE 470 TYPE(index_of_list),POINTER,INTENT(inout) :: CURSOR 471 ! 472 INTEGER :: i 473 DO i = 1,CURSOR%nrec 474 IF(associated(CURSOR%index(i)%data)) THEN 475 DEALLOCATE(CURSOR%index(i)%data) 476 NULLIFY(CURSOR%index(i)%data) 477 ENDIF 478 ENDDO 479 DEALLOCATE(CURSOR%index) 480 CURSOR%unit = -1 481 CURSOR%recl = -1 482 CURSOR%nrec = -1 483 DEALLOCATE(CURSOR) 484 NULLIFY(CURSOR) 485 ! 486 END SUBROUTINE dealloc_buffer 487 ! \/o\________\\\_________________________________________/^> 488END MODULE buiol 489! <<^V^\\=========================================//-//-//========//O\\// 490! 491MODULE buffers 492 ! 493 !! It includes QE interfaces to BUIOL module. 494 ! 495 USE kinds, ONLY: DP 496 USE buiol, ONLY: init_buiol, buiol_open_unit, buiol_close_unit, & 497 buiol_check_unit, buiol_get_ext, buiol_get_dir, & 498 buiol_read_record, buiol_write_record, is_init_buiol 499 ! 500 IMPLICIT NONE 501 ! 502 ! QE interfaces to BUIOL module 503 ! 504 PUBLIC :: open_buffer, get_buffer, save_buffer, close_buffer 505 ! 506 PRIVATE 507 INTEGER:: nunits = 0 508 ! 509CONTAINS 510 ! 511 !--------------------------------------------------------------------------------- 512 SUBROUTINE open_buffer( unit, extension, nword, io_level, exst, exst_file, direc ) 513 !------------------------------------------------------------------------------- 514 !! io_level>0: connect unit "unit" to file "wfc_dir"/"prefix"."extension" 515 !! (or "direc"/"prefix"."extension" if optional variable direc specified) 516 !! for direct I/O access, with record length = nword complex numbers; 517 !! on output, exst=T(F) if the file (does not) exists. 518 ! 519 !! io_level=0: open a buffer for storing records of length nword complex 520 !! numbers; store in memory file-related variables for later usage. 521 !! on output, exst=T(F) if the buffer is already allocated. 522 ! 523 !! On output, optional variable exst_file=T(F) if file is present (absent). 524 ! 525 USE io_files, ONLY : diropn, wfc_dir 526 ! 527 IMPLICIT NONE 528 ! 529 CHARACTER(LEN=*), INTENT(IN) :: extension 530 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: direc 531 INTEGER, INTENT(IN) :: unit, nword, io_level 532 LOGICAL, INTENT(OUT) :: exst 533 LOGICAL, INTENT(OUT), OPTIONAL :: exst_file 534 CHARACTER(LEN=256) :: save_dir 535 ! 536 INTEGER :: ierr 537 ! 538 ! not-so-elegant way to initialize the linked chain with units 539 ! 540 IF ( nunits == 0 ) CALL init_buiol() 541 ! 542 IF (extension == ' ') & 543 CALL errore( 'open_buffer', 'filename extension not given', 1 ) 544 ! 545 IF (PRESENT(direc)) THEN 546 save_dir = TRIM(direc) 547 ELSE 548 save_dir = TRIM(wfc_dir) 549 ENDIF 550 ! 551 IF ( io_level <= 0 ) THEN 552 CALL diropn( unit, extension, -1, exst, save_dir ) 553 IF (PRESENT(exst_file)) exst_file=exst 554 ierr = buiol_open_unit( unit, nword, extension, save_dir ) 555 IF ( ierr > 0 ) CALL errore( 'open_buffer', ' cannot open unit', 2 ) 556 exst = ( ierr == -1 ) 557 IF (exst) THEN 558 CALL infomsg( 'open_buffer', 'unit already opened' ) 559 nunits = nunits - 1 560 END IF 561 ELSE 562 CALL diropn( unit, extension, 2*nword, exst, save_dir ) 563 IF (PRESENT(exst_file)) exst_file=exst 564 ENDIF 565 nunits = nunits + 1 566 ! 567 RETURN 568 ! 569 END SUBROUTINE open_buffer 570 ! 571 ! 572 !---------------------------------------------------------------------------- 573 SUBROUTINE save_buffer( vect, nword, unit, nrec ) 574 !-------------------------------------------------------------------------- 575 !! Copy vect(1:nword) into the "nrec"-th record of a previously 576 !! allocated buffer / opened direct-access file, depending upon 577 !! how "open_buffer" was called. 578 ! 579 IMPLICIT NONE 580 ! 581 INTEGER, INTENT(IN) :: nword, unit, nrec 582 COMPLEX(DP), INTENT(INOUT) :: vect(nword) 583 INTEGER :: ierr 584 ! 585 ierr = buiol_check_unit( unit ) 586 IF( ierr > 0 ) THEN 587 ierr = buiol_write_record( unit, nword, nrec, vect ) 588 IF ( ierr > 0 ) & 589 CALL errore( 'save_buffer', 'cannot write record', unit ) 590#if defined(__DEBUG) 591 print *, 'save_buffer: record', nrec, ' written to unit', unit 592#endif 593 ELSE 594 CALL davcio( vect, 2*nword, unit, nrec, +1 ) 595 ENDIF 596 ! 597 END SUBROUTINE save_buffer 598 ! 599 !---------------------------------------------------------------------------- 600 SUBROUTINE get_buffer( vect, nword, unit, nrec ) 601 !!--------------------------------------------------------------------------- 602 !! Copy vect(1:nword) from the "nrec"-th record of a previously 603 !! allocated buffer / opened direct-access file, depending upon 604 !! how "open_buffer" was called. If buffer access was chosen 605 !! but buffer is not allocated, open the file, read from file. 606 ! 607 USE io_files, ONLY : diropn 608 ! 609 IMPLICIT NONE 610 ! 611 INTEGER, INTENT(IN) :: nword, unit, nrec 612 COMPLEX(DP), INTENT(OUT) :: vect(nword) 613 CHARACTER(LEN=256) :: extension, save_dir 614 INTEGER :: ierr 615 LOGICAL :: opnd 616 ! 617 ierr = buiol_check_unit( unit ) 618 IF( ierr > 0 ) THEN 619 ierr = buiol_read_record( unit, nword, nrec, vect ) 620#if defined(__DEBUG) 621 PRINT *, 'get_buffer: record', nrec, ' read from unit', unit 622#endif 623 IF ( ierr < 0 ) THEN 624 ! record not found: open file if not opened, read from it... 625 INQUIRE( UNIT = unit, OPENED = opnd ) 626 IF ( .NOT. opnd ) THEN 627 extension = buiol_get_ext(unit) 628 save_dir = buiol_get_dir(unit) 629 CALL diropn( unit, extension, 2*nword, opnd, save_dir ) 630 END IF 631 CALL davcio( vect, 2*nword, unit, nrec, -1 ) 632 ! ... and save to memory 633 ierr = buiol_write_record( unit, nword, nrec, vect ) 634 IF ( ierr /= 0 ) CALL errore( 'get_buffer', & 635 'cannot store record in memory', unit ) 636#if defined(__DEBUG) 637 PRINT *, 'get_buffer: record', nrec, ' read from file', unit 638#endif 639 ENDIF 640#if defined(__DEBUG) 641 PRINT *, 'get_buffer: record', nrec, ' read from unit', unit 642#endif 643 ELSE 644 CALL davcio( vect, 2*nword, unit, nrec, -1 ) 645 ENDIF 646 ! 647 END SUBROUTINE get_buffer 648 ! 649 !------------------------------------------------------------ 650 SUBROUTINE close_buffer( unit, status ) 651 !---------------------------------------------------------- 652 !! Close unit with status "status" ('keep' or 'delete') 653 !! deallocate related buffer if any; if "status='keep'" 654 !! save it to file (opening it if not already opened). 655 !! Does not complain if closing an already closed unit. 656 ! 657 USE io_files, ONLY : diropn 658 ! 659 IMPLICIT NONE 660 ! 661 INTEGER, INTENT(IN) :: unit 662 CHARACTER(LEN=*), INTENT(IN) :: status 663 ! 664 COMPLEX(dp), ALLOCATABLE :: vect(:) 665 CHARACTER(LEN=256) :: extension, save_dir 666 INTEGER :: n, ierr, nrec, nword 667 LOGICAL :: opnd 668 ! 669 IF ( .NOT. is_init_buiol ) RETURN 670 nword = buiol_check_unit( unit ) 671 ! 672 IF( nword > 0 ) THEN 673 ! data is in memory buffer 674 IF ( status == 'keep' .OR. status == 'KEEP' ) THEN 675 ! open file if not previously opened 676 INQUIRE( UNIT = unit, OPENED = opnd ) 677 IF ( .NOT. opnd ) THEN 678 extension = buiol_get_ext (unit) 679 save_dir = buiol_get_dir (unit) 680 CALL diropn( unit, extension, 2*nword, opnd, save_dir ) 681 ENDIF 682 ALLOCATE( vect(nword) ) 683 n = 1 684 10 CONTINUE 685 ierr = buiol_read_record( unit, nword, n, vect ) 686 IF ( ierr /= 0 ) GO TO 20 687 CALL davcio( vect, 2*nword, unit, n, +1 ) 688 n = n+1 689 GO TO 10 690 20 DEALLOCATE( vect ) 691 ENDIF 692 ierr = buiol_close_unit( unit ) 693 if ( ierr < 0 ) & 694 CALL errore( 'close_buffer', 'error closing', ABS(unit) ) 695#if defined(__DEBUG) 696 PRINT *, 'close_buffer: unit ',unit, 'closed' 697#endif 698 ENDIF 699 INQUIRE( UNIT = unit, OPENED = opnd ) 700 IF ( opnd ) CLOSE( UNIT = unit, STATUS = status ) 701 nunits = nunits - 1 702 ! 703 END SUBROUTINE close_buffer 704 ! 705 ! end interface for old "buffers" module 706 ! 707END MODULE buffers 708