MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_datacube.t
Go to the documentation of this file.
2 use, intrinsic :: ieee_arithmetic
3 implicit none
4 double precision :: globaltime
5 integer :: i, found
6 integer :: pos_index
7 integer, parameter :: nclt = 90, nlons = 180
8
9contains
10
11 subroutine get_datacube_arrays(target_time, cme_number, base_file, found, clts, lons, mask, vr, vp, vt, br, bt, bp, md, temp)
12 implicit none
13 double precision, intent(in) :: target_time
14 integer, intent(in) :: cme_number
15 character(len=*), intent(in) :: base_file
16 integer, intent(out) :: found
17 double precision, allocatable, intent(out) :: clts(:), lons(:)
18 real, allocatable, intent(out) :: vr(:), vt(:), vp(:)
19 real, allocatable, intent(out) :: br(:), bt(:), bp(:)
20 real, allocatable, intent(out) :: md(:), temp(:), mask(:)
21
22 double precision :: min_diff, latest_time, pi, file_time
23 integer :: unit, ios, size(9), size_2(9)
24 integer :: ierr, nfiles, n, i, j, ndata, pos
25 integer :: unit_tmp, file_num
26 integer :: time_int
27 integer :: clt_size, lon_size
28 character(len=256) :: binfile, cltsfile, lonsfile
29 character(len=256) :: output_dir, fullpath, cme_str
30 character(len=256) :: cmd, line, filename, bestfile
31 character(len=256), allocatable :: tmpfile
32 character(len=256) :: base_name, number_str
33 character(len=256), allocatable :: files(:)
34 character(len=20) :: time_str
35 logical :: file_exists, in_mask
36 ! Initialize outputs
37 found = 0
38 if (allocated(clts)) deallocate(clts)
39 if (allocated(lons)) deallocate(lons)
40 if (allocated(mask)) deallocate(mask)
41 if (allocated(vr)) deallocate(vr)
42 if (allocated(vp)) deallocate(vp)
43 if (allocated(vt)) deallocate(vt)
44 if (allocated(br)) deallocate(br)
45 if (allocated(bt)) deallocate(bt)
46 if (allocated(bp)) deallocate(bp)
47 if (allocated(md)) deallocate(md)
48 if (allocated(temp)) deallocate(temp)
49 ! --- Step 1: List all files in datacube folder ---
50 pos = index(base_file, '/', back=.true.)
51 if (pos > 0) then
52 output_dir = base_file(1:pos)
53 else
54 output_dir = './'
55 end if
56
57 write(cme_str, '(I0)') cme_number
58 fullpath = trim(output_dir)//'datacube/cme_'//trim(cme_str)
59 tmpfile=trim(fullpath)//'/file_list.txt'
60
61 ! Check if temp file exists and has content
62 inquire(file=trim(tmpfile), exist=file_exists)
63 if (.not. file_exists) then
64 print *, "No file list file found in directory: ", trim(fullpath)
65 return
66 end if
67
68 ! Count number of files
69 open(newunit=unit_tmp, file=tmpfile, status='old', action='read', iostat=ierr)
70 if (ierr /= 0) then
71 print *, "Error opening temp file"
72 return
73 end if
74
75 nfiles = 0
76 do
77 read(unit_tmp, '(A)', iostat=ios) line
78 if (ios /= 0) exit
79 if (trim(line) /= '') nfiles = nfiles + 1
80 end do
81
82 if (nfiles == 0) then
83 close(unit_tmp)
84 print *, "No valid .bin files found"
85 return
86 end if
87
88 rewind(unit_tmp)
89
90 ! Read file names
91 allocate(files(nfiles), stat=ierr)
92 if (ierr /= 0) then
93 print *, "Error allocating files array"
94 close(unit_tmp)
95 return
96 end if
97
98 j = 1
99 do
100 read(unit_tmp, '(A)', iostat=ios) line
101 if (ios /= 0) exit
102 if (trim(line) /= '') then
103 files(j) = trim(line)
104 j = j + 1
105 end if
106 end do
107 close(unit_tmp)
108
109 ! --- Step 2: Find latest file time ---
110 latest_time = -1.0d0
111 do j = 1, nfiles
112 pos = index(files(j), '/', back=.true.)
113 if (pos == 0) then
114 base_name = trim(files(j))
115 else
116 base_name = trim(files(j)(pos+1:))
117 end if
118
119 pos = index(base_name, '.bin')
120 if (pos > 1) then
121 number_str = base_name(1:pos-1)
122 read(number_str, *, iostat=ierr) file_num
123 file_time = file_num/60.0d0
124 if (ierr == 0) then
125 if (file_time > latest_time) latest_time = file_time
126 end if
127 end if
128 end do
129 ! --- Step 3: Check if input time is within range ---
130 if (target_time > latest_time) then
131 ! print *, "Target time exceeds latest available data time"
132 deallocate(files)
133 return
134 end if
135
136 ! --- Step 4: Find closest file by time ---
137 min_diff = huge(min_diff)
138 bestfile = ""
139 do j = 1, nfiles
140 pos = index(files(j), '/', back=.true.)
141 if (pos == 0) then
142 base_name = trim(files(j))
143 else
144 base_name = trim(files(j)(pos+1:))
145 end if
146
147 pos = index(base_name, '.bin')
148 if (pos > 1) then
149 number_str = base_name(1:pos-1)
150 read(number_str, *, iostat=ierr) file_time
151 file_time = file_time/60.0d0
152 if (ierr == 0) then
153 if (abs(file_time - target_time) < min_diff) then
154 min_diff = abs(file_time - target_time)
155 bestfile = files(j)
156 end if
157 end if
158 end if
159 end do
160
161 if (len_trim(bestfile) == 0) then
162 print *, "Could not determine best matching file"
163 deallocate(files)
164 return
165 end if
166
167 ! --- Step 5: Read datacube files ---
168
169 ! Extract output directory from base_file path
170 pos = index(base_file, '/', back=.true.)
171 if (pos > 0) then
172 output_dir = base_file(1:pos)
173 else
174 output_dir = './'
175 end if
176
177 write(cme_str, '(I0)') cme_number
178
179 binfile = trim(output_dir) // 'datacube/cme_' // trim(cme_str) // '/' // trim(bestfile)
180 inquire(file=binfile, exist=file_exists)
181 if (.not. file_exists) then
182 print *, "Binary datacube file does not exist: ", trim(binfile)
183 return
184 end if
185
186 ! Open binary file to read
187 open(newunit=unit, file=binfile, status='old', access='stream', form='unformatted', action='read', iostat=ios)
188 if (ios /= 0) then
189 print *, "Error opening datacube binary file: ", trim(binfile)
190 return
191 end if
192 read(unit) size
193
194 ! Allocate all arrays of length size
195 allocate(mask(size(1)), vr(size(2)), vp(size(3)), vt(size(4)), br(size(5)), bt(size(6)), bp(size(7)), md(size(8)), temp(size(9)), stat=ios)
196 if (ios /= 0) then
197 print *, "Error allocating arrays of size ", size
198 close(unit)
199 return
200 end if
201
202 ! Read arrays sequentially in the fixed order
203 read(unit) mask
204 read(unit) vr
205 read(unit) vt
206 read(unit) vp
207 read(unit) br
208 read(unit) bt
209 read(unit) bp
210 read(unit) md
211 read(unit) temp
212
213 close(unit)
214
215
216 ! Read clts and lons arrays from separate binary files
217 clt_size = 90
218 lon_size = 180
219
220 pi = 4.0d0 * atan(1.0d0)
221
222 allocate(clts(clt_size), lons(lon_size))
223 do i = 1, (clt_size)
224 clts(i) = dble(i-1) * pi / dble(clt_size)
225 end do
226
227 do i = 1, (lon_size)
228 lons(i) = -pi + dble(i-1) * 2*pi / dble(lon_size)
229 end do
230 found = 1 ! success
231 end subroutine get_datacube_arrays
232
233 subroutine get_value(clt, lon_in, ts_magnetogram, clts, lons, mask, vr, vp, vt, br, bt, bp, temp, md, ndata, &
234 found, vr_val, vp_val, vt_val, br_val, bt_val, bp_val, md_val, temp_val)
235 implicit none
236 double precision, intent(in) :: clt, lon_in, ts_magnetogram
237 double precision, intent(in) :: clts(:), lons(:)
238 real, intent(in) :: mask(:), vr(:), vp(:), vt(:), br(:), bt(:), bp(:), temp(:), md(:)
239 integer, intent(in) :: ndata
240 integer, intent(out) :: found
241 double precision, intent(out) :: vr_val, vp_val, vt_val, br_val, bt_val, bp_val, md_val, temp_val
242
243 double precision :: synoptic_correction, lon, pi
244 real :: val_1(8), val_2(8), val_min(8), val_max(8)
245 integer :: i, j, k
246
247 ! Correct synoptic rotation
248 pi = 4.0d0 * atan(1.0d0)
249 synoptic_correction = 2*pi/27.27/24.0d0
250
251 lon = modulo(lon_in + synoptic_correction*ts_magnetogram + pi, 2*pi) -pi
252 ! Initialize outputs
253 found = 0
254
255 vr_val = ieee_value(vr_val, ieee_quiet_nan)
256 vp_val = ieee_value(vp_val, ieee_quiet_nan)
257 vt_val = ieee_value(vt_val, ieee_quiet_nan)
258 br_val = ieee_value(br_val, ieee_quiet_nan)
259 bt_val = ieee_value(bt_val, ieee_quiet_nan)
260 bp_val = ieee_value(bp_val, ieee_quiet_nan)
261 md_val = ieee_value(md_val, ieee_quiet_nan)
262 temp_val = ieee_value(temp_val, ieee_quiet_nan)
263
264
265 ! Get position index
266 i = get_position_index(clt, lon, clts, lons)
267 if (i == -1) return
268
269 ! Find matching data point
270 do j = 1, ndata
271 if (nint(mask(j)) == i) then
272 found = 1
273 vr_val = vr(min(j, size(vr)))
274 vp_val = vp(min(j, size(vp)))
275 vt_val = vt(min(j, size(vt)))
276 br_val = br(min(j, size(br)))
277 bt_val = bt(min(j, size(bt)))
278 bp_val = bp(min(j, size(bp)))
279 md_val = md(min(j, size(md)))
280 temp_val = temp(min(j, size(temp)))
281 exit
282 end if
283 end do
284
285 end subroutine get_value
286
287 function get_position_index(clt_val, lon_val, clts, lons) result(position_index)
288 implicit none
289 double precision, intent(in) :: clt_val, lon_val
290 double precision, intent(in) :: clts(:), lons(:)
291
292 double precision :: current_diff, min_diff
293 integer :: position_index
294 integer :: clt_index, lon_index, n
295
296 ! Find closest clt index
297 clt_index = 1
298 min_diff = abs(clts(1) - real(clt_val))
299 do n = 2, size(clts)
300 current_diff = abs(clts(n) - real(clt_val))
301 if (current_diff < min_diff) then
302 min_diff = current_diff
303 clt_index = n
304 end if
305 end do
306
307 ! Find closest lon index
308 lon_index = 1
309 min_diff = abs(lons(1) - real(lon_val))
310 do n = 2, size(lons)
311 current_diff = abs(lons(n) - real(lon_val))
312 if (current_diff < min_diff) then
313 min_diff = current_diff
314 lon_index = n
315 end if
316 end do
317
318 ! Convert to 0-based index
319 lon_index = lon_index - 1
320 clt_index = clt_index - 1
321
322 if (clt_index >= 0 .and. lon_index >= 0) then
323 position_index = lon_index + clt_index * size(lons)
324 else
325 position_index = -1
326 end if
327 end function get_position_index
328
329 function round5(x) result(r)
330 implicit none
331 real, intent(in) :: x ! input variable (double precision)
332 real :: r ! result
333 real, parameter :: scale = 1.0d5
334
335 ! Multiply, round to nearest integer, then divide back
336 r = nint(x * scale) / scale
337 end function round5
338
339end module mod_datacube
340
341
342
integer pos_index
Definition mod_datacube.t:6
integer function get_position_index(clt_val, lon_val, clts, lons)
integer, parameter nlons
Definition mod_datacube.t:7
real function round5(x)
double precision globaltime
Definition mod_datacube.t:4
integer, parameter nclt
Definition mod_datacube.t:7
integer found
Definition mod_datacube.t:5
subroutine get_value(clt, lon_in, ts_magnetogram, clts, lons, mask, vr, vp, vt, br, bt, bp, temp, md, ndata, found, vr_val, vp_val, vt_val, br_val, bt_val, bp_val, md_val, temp_val)
subroutine get_datacube_arrays(target_time, cme_number, base_file, found, clts, lons, mask, vr, vp, vt, br, bt, bp, md, temp)