The Elk Code
modramdisk.f90
Go to the documentation of this file.
1 
2 ! Copyright (C) 2021 J. K. Dewhurst, S. Sharma and E. K. U. Gross.
3 ! This file is distributed under the terms of the GNU General Public License.
4 ! See the file COPYING for license details.
5 
6 module modramdisk
7 
8 ! ramdisk is .true. if the RAM disk should be used
9 logical ramdisk
10 ! maximum allowed number of files on the RAM disk
11 integer, parameter, private :: maxfiles=32
12 ! maximum number of records per file
13 integer, parameter, private :: maxrec=32768
14 ! wrtdsk is .true. if files should also be written to disk
15 logical wrtdsk,wrtdsk0
16 
17 ! record data stored as 4-byte words
18 type, private :: rec_t
19  integer(4), allocatable :: dat(:)
20 end type
21 
22 ! RAM disk file consisting of the filename and an array of records
23 type, private :: file_t
24  character(len=:), allocatable :: fname
25  type(rec_t), allocatable :: rec(:)
26 end type
27 
28 ! arrays of files constituting the RAM disk
29 type(file_t), allocatable, private :: file(:)
30 
31 ! private subroutines
32 private findfile,openfile
33 
34 contains
35 
36 subroutine initrd
37 ! this subroutine should not be called from a parallel region
38 implicit none
39 ! local variables
40 integer i
41 ! check if the RAM disk is already initialised
42 if (allocated(file)) return
43 ! allocate the files array and null the file names
44 allocate(file(maxfiles))
45 do i=1,maxfiles
46  file(i)%fname=''
47 end do
48 end subroutine
49 
50 subroutine findfile(fname,fnum)
51 implicit none
52 ! arguments
53 character(*), intent(in) :: fname
54 integer, intent(out) :: fnum
55 ! local variables
56 integer i
57 if (.not.allocated(file)) then
58  write(*,*)
59  write(*,'("Error(findfile): RAM disk not initialised")')
60  write(*,*)
61  stop
62 end if
63 fnum=0
64 do i=1,maxfiles
65  if (file(i)%fname == fname) then
66  fnum=i
67  return
68  end if
69 end do
70 end subroutine
71 
72 subroutine openfile(fname,fnum)
73 implicit none
74 ! arguments
75 character(*), intent(in) :: fname
76 integer, intent(out) :: fnum
77 ! local variables
78 integer i
79 ! check to see if the file already exists
80 call findfile(fname,fnum)
81 if (fnum /= 0) return
82 ! use the first available file number
83 do i=1,maxfiles
84  if (file(i)%fname == '') then
85 ! assign the filename
86  file(i)%fname=fname
87 ! allocate the record array
88  allocate(file(i)%rec(maxrec))
89  fnum=i
90  return
91  end if
92 end do
93 write(*,*)
94 write(*,'("Error(openfile): too many RAM disk files open : ",I8)') maxfiles
95 write(*,*)
96 stop
97 end subroutine
98 
99 subroutine delfrd(fname)
100 ! this subroutine should not be called from a parallel region
101 implicit none
102 ! arguments
103 character(*), intent(in) :: fname
104 ! local variables
105 integer fnum,i
106 ! determine the file number
107 call findfile(fname,fnum)
108 ! return if the file does not exist
109 if (fnum == 0) return
110 ! erase filename
111 file(fnum)%fname=''
112 ! deallocate associated arrays
113 do i=1,maxrec
114  if (allocated(file(fnum)%rec(i)%dat)) deallocate(file(fnum)%rec(i)%dat)
115 end do
116 deallocate(file(fnum)%rec)
117 end subroutine
118 
119 subroutine putrd(fname,irec,n1,n2,n3,v1,v2,nrv,rva,nzv,zva)
120 ! this subroutine should be called from an OpenMP critical section
121 implicit none
122 ! arguments
123 character(*), intent(in) :: fname
124 integer, intent(in) :: irec
125 integer, optional, intent(in) :: n1,n2,n3
126 real(8), optional, intent(in) :: v1(3),v2(3)
127 integer, optional, intent(in) :: nrv
128 real(8), optional, intent(in) :: rva(*)
129 integer, optional, intent(in) :: nzv
130 complex(8), optional, intent(in) :: zva(*)
131 ! local variables
132 integer fnum,n,i,j
133 ! check that the record number does not exceed the maximum
134 if (irec > maxrec) then
135 ! fail safe by enabling disk writes
136  wrtdsk=.true.
137  return
138 end if
139 ! find the record length in 4-byte words
140 n=0
141 if (present(n1)) n=n+1
142 if (present(n2)) n=n+1
143 if (present(n3)) n=n+1
144 if (present(v1)) n=n+6
145 if (present(v2)) n=n+6
146 if (present(rva)) then
147  if (present(nrv)) then
148  n=n+2*nrv
149  else
150  write(*,*)
151  write(*,'("Error(putrd): missing argument nrv")')
152  write(*,*)
153  stop
154  end if
155 end if
156 if (present(zva)) then
157  if (present(nzv)) then
158  n=n+4*nzv
159  else
160  write(*,*)
161  write(*,'("Error(putrd): missing argument nzv")')
162  write(*,*)
163  stop
164  end if
165 end if
166 ! open the file
167 call openfile(fname,fnum)
168 ! allocate the record data array if required
169 if (allocated(file(fnum)%rec(irec)%dat)) then
170  if (size(file(fnum)%rec(irec)%dat) < n) then
171  deallocate(file(fnum)%rec(irec)%dat)
172  end if
173 end if
174 if (.not.allocated(file(fnum)%rec(irec)%dat)) then
175  allocate(file(fnum)%rec(irec)%dat(n))
176 end if
177 i=1
178 if (present(n1)) then
179  file(fnum)%rec(irec)%dat(i)=n1
180  i=i+1
181 end if
182 if (present(n2)) then
183  file(fnum)%rec(irec)%dat(i)=n2
184  i=i+1
185 end if
186 if (present(n3)) then
187  file(fnum)%rec(irec)%dat(i)=n3
188  i=i+1
189 end if
190 if (present(v1)) then
191  j=i+5
192  file(fnum)%rec(irec)%dat(i:j)=transfer(v1(1:3),file(fnum)%rec(irec)%dat(i:j))
193  i=i+6
194 end if
195 if (present(v2)) then
196  j=i+5
197  file(fnum)%rec(irec)%dat(i:j)=transfer(v2(1:3),file(fnum)%rec(irec)%dat(i:j))
198  i=i+6
199 end if
200 if (present(rva)) then
201  j=i+2*nrv-1
202  file(fnum)%rec(irec)%dat(i:j)=transfer(rva(1:nrv), &
203  file(fnum)%rec(irec)%dat(i:j))
204  i=i+2*nrv
205 end if
206 if (present(zva)) then
207  j=i+4*nzv-1
208  file(fnum)%rec(irec)%dat(i:j)=transfer(zva(1:nzv), &
209  file(fnum)%rec(irec)%dat(i:j))
210 end if
211 end subroutine
212 
213 subroutine getrd(fname,irec,tgs,n1,n2,n3,v1,v2,nrv,rva,nzv,zva)
214 implicit none
215 ! arguments
216 character(*), intent(in) :: fname
217 integer, intent(in) :: irec
218 logical, intent(out) :: tgs
219 integer, optional, intent(out) :: n1,n2,n3
220 real(8), optional, intent(out) :: v1(3),v2(3)
221 integer, optional, intent(in) :: nrv
222 real(8), optional, intent(out) :: rva(*)
223 integer, optional, intent(in) :: nzv
224 complex(8), optional, intent(out) :: zva(*)
225 ! local variables
226 integer fnum,n,i
227 if (present(rva)) then
228  if (.not.present(nrv)) then
229  write(*,*)
230  write(*,'("Error(getrd): missing argument nrv")')
231  write(*,*)
232  stop
233  end if
234 end if
235 if (present(zva)) then
236  if (.not.present(nzv)) then
237  write(*,*)
238  write(*,'("Error(getrd): missing argument nzv")')
239  write(*,*)
240  stop
241  end if
242 end if
243 tgs=.false.
244 if (irec > maxrec) return
245 ! determine the file number
246 call findfile(fname,fnum)
247 ! return unsuccessfully if file is not found or record is unavailable
248 if (fnum == 0) return
249 if (.not.allocated(file(fnum)%rec(irec)%dat)) return
250 n=size(file(fnum)%rec(irec)%dat)
251 i=1
252 if (present(n1)) then
253  if (n < 1) return
254  n1=file(fnum)%rec(irec)%dat(i)
255  i=i+1
256  n=n-1
257 end if
258 if (present(n2)) then
259  if (n < 1) return
260  n2=file(fnum)%rec(irec)%dat(i)
261  i=i+1
262  n=n-1
263 end if
264 if (present(n3)) then
265  if (n < 1) return
266  n3=file(fnum)%rec(irec)%dat(i)
267  i=i+1
268  n=n-1
269 end if
270 if (present(v1)) then
271  if (n < 6) return
272  v1(1:3)=transfer(file(fnum)%rec(irec)%dat(i:i+5),v1(1:3))
273  i=i+6
274  n=n-6
275 end if
276 if (present(v2)) then
277  if (n < 6) return
278  v2(1:3)=transfer(file(fnum)%rec(irec)%dat(i:i+5),v2(1:3))
279  i=i+6
280  n=n-6
281 end if
282 if (present(rva)) then
283  if (n < 2*nrv) return
284  rva(1:nrv)=transfer(file(fnum)%rec(irec)%dat(i:i+2*nrv-1),rva(1:nrv))
285  i=i+2*nrv
286  n=n-2*nrv
287 end if
288 if (present(zva)) then
289  if (n < 4*nzv) return
290  zva(1:nzv)=transfer(file(fnum)%rec(irec)%dat(i:i+4*nzv-1),zva(1:nzv))
291 end if
292 ! flag the get operation as successful
293 tgs=.true.
294 end subroutine
295 
296 subroutine rdstatus
297 ! this subroutine should not be called from a parallel region
298 implicit none
299 ! local variables
300 integer nf,nr,i,j
301 integer(8) m,n
302 write(*,*)
303 write(*,'("Info(rdstatus):")')
304 if (.not.allocated(file)) then
305  write(*,'(" RAM disk not initialised")')
306  return
307 end if
308 nf=0
309 n=0
310 do i=1,maxfiles
311  if (file(i)%fname /= '') then
312  write(*,*)
313  write(*,'(" Filename : ",A)') file(i)%fname
314  nf=nf+1
315  nr=0
316  m=0
317  do j=1,maxrec
318  if (allocated(file(i)%rec(j)%dat)) then
319  nr=nr+1
320  m=m+size(file(i)%rec(j)%dat)
321  end if
322  end do
323  n=n+m
324  write(*,'(" number of records : ",I8)') nr
325  write(*,'(" total number of bytes : ",I14)') 4*m
326  end if
327 end do
328 write(*,*)
329 write(*,'(" Number of files on RAM disk : ",I4)') nf
330 write(*,'(" Total number of bytes used by RAM disk : ",I14)') 4*n
331 end subroutine
332 
333 end module
334 
logical ramdisk
Definition: modramdisk.f90:9
subroutine putrd(fname, irec, n1, n2, n3, v1, v2, nrv, rva, nzv, zva)
Definition: modramdisk.f90:120
type(file_t), dimension(:), allocatable, private file
Definition: modramdisk.f90:29
subroutine rdstatus
Definition: modramdisk.f90:297
subroutine getrd(fname, irec, tgs, n1, n2, n3, v1, v2, nrv, rva, nzv, zva)
Definition: modramdisk.f90:214
subroutine, private findfile(fname, fnum)
Definition: modramdisk.f90:51
logical wrtdsk
Definition: modramdisk.f90:15
subroutine delfrd(fname)
Definition: modramdisk.f90:100
logical wrtdsk0
Definition: modramdisk.f90:15
subroutine initrd
Definition: modramdisk.f90:37
subroutine, private openfile(fname, fnum)
Definition: modramdisk.f90:73
integer, parameter, private maxfiles
Definition: modramdisk.f90:11
integer, parameter, private maxrec
Definition: modramdisk.f90:13