use IO_int, ONLY: io_control, io_connect, io_disconnect
use IO_m, ONLY: OP_RD_CL, OP_WR_CL, OP_APP_CL, &
DUMP, VERIFY, REP, LOG, NONE, &
io_status, IO_NO_ERROR
integer :: ID, ierr
call io_control(ACTION=OP_RD_CL, COM=REP, SEC=(/1,2,3/), MODE=VERIFY, ID=ID)
ierr = io_connect('ndb.dipoles', ID=ID)
if (ierr == 0) then
ierr = io_DIPOLES(ID) ! Database-specific read routine
call io_disconnect(ID)
endif
integer :: ID, ierr
call io_control(ACTION=OP_WR_CL, COM=NONE, SEC=(/1,2,3/), MODE=DUMP, ID=ID)
ierr = io_connect('ndb.my_data', subfolder='SAVE', type=2, ID=ID)
! Write header
call io_elemental(ID, VAR='PARS', VAR_SZ=0)
call io_elemental(ID, VAR='nkpts', I0=nk)
! Write data
call io_bulk(ID, VAR='energies', VAR_SZ=(/nb, nk/))
call io_bulk(ID, R2=E_array)
call io_disconnect(ID)
integer :: ID, ierr, ik, ik_global
logical :: do_io
do ik = 1, PAR_IND_Xk%n(myid+1)
ik_global = PAR_IND_Xk%element_1D(ik)
do_io = .TRUE. ! This CPU participates
call io_control(ACTION=OP_WR_CL, ID=ID, DO_IT=do_io)
ierr = io_connect('ndb.wf', ID=ID)
! Write fragment for this k-point
call io_fragment(ID, ID_frag, i_fragment=ik_global)
call io_bulk(ID_frag, C2=wf(:,:,ik))
call io_disconnect(ID_frag)
call io_disconnect(ID)
enddo
use parallel_m, ONLY: PAR_IND_Xk
integer :: ID, ierr
! All CPUs in PAR_IND_Xk%COMM participate
call io_control(ACTION=OP_WR_CL, ID=ID, COMM=PAR_IND_Xk%COMM)
ierr = io_connect('ndb.response', ID=ID)
call io_bulk(ID, VAR='Chi', VAR_SZ=(/ng, ng, nw/))
! Each CPU writes its frequency slice
do iw = 1, my_nw
iw_global = my_w_index(iw)
call io_bulk(ID, C2=chi_local(:,:,iw), IPOS=(/1, 1, iw_global/))
enddo
call io_disconnect(ID)
integer :: nk_expected, nk_read
nk_expected = 100
call io_control(ACTION=OP_RD_CL, MODE=VERIFY, ID=ID)
ierr = io_connect('ndb.kindx', ID=ID)
call io_elemental(ID, VAR='nkpts', I0=nk_read, DB_I0=nk_expected, &
CHECK=.TRUE., OP=(/'=='/))
if (io_status(ID) /= IO_NO_ERROR) then
call error('Incompatible k-point grid')
endif
call io_disconnect(ID)
integer :: ID, ID_frag, ik, ik_global
call io_control(ACTION=OP_RD_CL, ID=ID)
ierr = io_connect('ndb.dipoles', ID=ID)
! Read header/dimensions
ierr = io_DIPOLES(ID, HEADER_ONLY=.TRUE.)
! Each CPU reads its k-point fragments
do ik = 1, PAR_IND_Xk%n(myid+1)
ik_global = PAR_IND_Xk%element_1D(ik)
call io_fragment(ID, ID_frag, i_fragment=ik_global)
call io_bulk(ID_frag, C2=dipole_matrix(:,:,ik))
call io_disconnect(ID_frag)
enddo
call io_disconnect(ID)
| Code | Name | Description |
|---|---|---|
OP_RD_CL |
Open-Read-Close | Open for reading, then close |
OP_WR_CL |
Open-Write-Close | Open for writing, then close |
OP_APP_CL |
Open-Append-Close | Open for appending, then close |
OP_RD |
Open-Read | Open for reading (keep open) |
OP_WR |
Open-Write | Open for writing (keep open) |
OP_APP |
Open-Append | Open for appending (keep open) |
RD |
Read | Read (already open) |
WR |
Write | Write (already open) |
RD_CL |
Read-Close | Read and close |
WR_CL |
Write-Close | Write and close |
| Code | Description |
|---|---|
DUMP |
Write/read data without verification |
VERIFY |
Read and verify compatibility with expected values |
| Code | Description |
|---|---|
REP |
Report to report file (r-*) |
LOG |
Report to log file (l-*) |
NONE |
Silent (no reporting) |
| Code | Value | Description |
|---|---|---|
IO_NO_ERROR |
0 | Success |
IO_NO_DATABASE |
-1 | Database file not found |
IO_INCOMPATIBLE_VAR |
-2 | Incompatible variable |
IO_GENERIC_ERROR |
-3 | Generic error |
IO_NO_BINDING_ERROR |
-4 | No binding error |
IO_OUTDATED_DB |
-5 | Database format outdated |
IO_NOT_ALLOWED |
-6 | CPU not allowed to access |
! Integer
call io_elemental(ID, VAR='nkpts', I0=nk)
! Real
call io_elemental(ID, VAR='temperature', R0=T, UNIT=1.0)
! Double precision
call io_elemental(ID, VAR='energy', D0=E_total)
! Complex
call io_elemental(ID, VAR='phase', C0=phase_factor)
! Logical
call io_elemental(ID, VAR='converged', L0=is_converged)
! String
call io_elemental(ID, VAR='xc_functional', CH0='PBE')
! Integer array
call io_elemental(ID, VAR='k_indices', I1=k_idx)
! Real array
call io_elemental(ID, VAR='weights', R1=wk)
! String array
call io_elemental(ID, VAR='labels', CH1=atom_labels)
! Read and verify
call io_elemental(ID, VAR='nkpts', I0=nk_read, DB_I0=nk_expected, &
CHECK=.TRUE., OP=(/'=='/))
! Read with warning (not error)
call io_elemental(ID, VAR='temperature', R0=T_read, DB_R0=T_expected, &
WARN=.TRUE., OP=(/'<='/))
'==' : Equal'/=' : Not equal'<' : Less than'<=' : Less than or equal'>' : Greater than'>=' : Greater than or equal! 2D real array
call io_bulk(ID, VAR='density', VAR_SZ=(/nx, ny/))
! 3D complex array
call io_bulk(ID, VAR='wavefunction', VAR_SZ=(/ng, nb, nk/))
! 4D integer array
call io_bulk(ID, VAR='indices', VAR_SZ=(/n1, n2, n3, n4/))
! Write entire array
call io_bulk(ID, R2=density_array)
! Read entire array
call io_bulk(ID, C3=wf_array)
! Write slice (starting at IPOS)
call io_bulk(ID, R2=slice_array, IPOS=(/1, iz/))
| Prefix | Type | Dimensions |
|---|---|---|
I0-I5 |
Integer | Scalar to 5D |
R0-R5 |
Real (SP) | Scalar to 5D |
D0-D5 |
Double (DP) | Scalar to 5D |
C0-C5 |
Complex (SP) | Scalar to 5D |
Z0-Z5 |
Complex (DP) | Scalar to 5D |
L0-L4 |
Logical | Scalar to 4D |
!$omp parallel default(shared)
! Computation (all threads)
!$omp do
do ib = 1, nbands
call compute_something(ib, result)
!$omp critical
accumulator = accumulator + result
!$omp end critical
enddo
!$omp end do
! I/O (master thread only)
!$omp master
call io_bulk(ID, R1=accumulator)
!$omp end master
!$omp end parallel
!$omp parallel
! ... computation ...
!$omp single
call io_elemental(ID, VAR='result', R0=final_result)
!$omp end single
!$omp end parallel
yambo -V io
if (io_status(ID) /= IO_NO_ERROR) then
write(*,*) 'I/O error code:', io_status(ID)
endif
use IO_m, ONLY: io_file, io_PAR_cpu, io_PAR_comm
write(*,*) 'File:', trim(io_file(ID))
write(*,*) 'CPU allowed:', io_PAR_cpu(ID)
write(*,*) 'MPI comm:', io_PAR_comm(ID)
❌ Don't do this:
! Forgot to call io_control before io_connect
ierr = io_connect('ndb.dipoles', ID=ID) ! ID is undefined!
✅ Do this:
call io_control(ACTION=OP_RD_CL, ID=ID) ! ID is assigned here
ierr = io_connect('ndb.dipoles', ID=ID)
❌ Don't do this:
! All CPUs try to write without coordination
call io_control(ACTION=OP_WR_CL, ID=ID)
ierr = io_connect('ndb.data', ID=ID)
call io_bulk(ID, R1=my_data) ! Race condition!
✅ Do this:
! Use DO_IT or COMM to coordinate
call io_control(ACTION=OP_WR_CL, ID=ID, DO_IT=(myid==0))
ierr = io_connect('ndb.data', ID=ID)
if (myid == 0) call io_bulk(ID, R1=my_data)
❌ Don't do this:
!$omp parallel
! All threads try to do I/O
call io_bulk(ID, R1=thread_data) ! Not thread-safe!
!$omp end parallel
✅ Do this:
!$omp parallel
!$omp master
call io_bulk(ID, R1=shared_data)
!$omp end master
!$omp end parallel
❌ Slow:
do ik = 1, nk
call io_elemental(ID, VAR='energy', R0=E(ik)) ! nk calls
enddo
✅ Fast:
call io_elemental(ID, VAR='energies', R1=E) ! 1 call
✅ Good for parallel access:
! Each CPU reads its own fragment
call io_fragment(ID, ID_frag, i_fragment=my_ik)
call io_bulk(ID_frag, C2=wf_local)
Compile with:
./configure --enable-hdf5-compression
Reduces file size by ~2-5× with minimal performance impact.
Compile with:
./configure --enable-hdf5-par-io
Then use:
call io_control(ACTION=OP_WR_CL, COMM=my_comm, ID=ID)
| Type | Description |
|---|---|
1 |
NetCDF (default) |
2 |
HDF5 (NetCDF-4) |
-2 |
Binary (unformatted) |
-4 |
Binary (formatted) |
doc/IO_System_Architecture.mddoc/IO_System_Flowchart.mdsrc/Yio/src/modules/mod_IO.FQuick Help: Search for io_control in existing code to see usage examples!