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