MFC
Exascale flow solver
Loading...
Searching...
No Matches
m_data_output.fpp.f90
Go to the documentation of this file.
1# 1 "/home/runner/work/MFC/MFC/src/pre_process/m_data_output.fpp"
2!>
3!! @file
4!! @brief Contains module m_data_output
5
6!> @brief Writes grid and initial condition data to serial or parallel output files
8
11 use m_helper
12 use m_mpi_proxy
13#ifdef MFC_MPI
14 use mpi
15#endif
16
19 use m_helper
24 use m_thermochem, only: species_names
25 use m_helper
27
28 implicit none
29
30 private
33
34 type(scalar_field), allocatable, dimension(:) :: q_cons_temp
35
36 abstract interface
37
38 !> Interface for the conservative data
39 impure subroutine s_write_abstract_data_files(q_cons_vf, q_prim_vf, bc_type, q_T_sf)
40
41 import :: scalar_field, integer_field, sys_size, m, n, p, pres_field, num_dims
42
43 type(scalar_field), dimension(sys_size), intent(inout) :: q_cons_vf, q_prim_vf
44 type(integer_field), dimension(1:num_dims,-1:1), intent(in) :: bc_type
45 type(scalar_field), intent(inout), optional :: q_t_sf
46
47 end subroutine s_write_abstract_data_files
48 end interface
49
50 !> Time-step folder into which grid and initial condition data will be placed
51 character(LEN=path_len + 2*name_len), private :: t_step_dir
52 character(LEN=path_len + 2*name_len), public :: restart_dir !< Restart data folder
53 procedure(s_write_abstract_data_files), pointer :: s_write_data_files => null()
54
55contains
56
57 !> Writes grid and initial condition data files to the "0" time-step directory in the local processor rank folder
58 impure subroutine s_write_serial_data_files(q_cons_vf, q_prim_vf, bc_type, q_T_sf)
59
60 type(scalar_field), dimension(sys_size), intent(inout) :: q_cons_vf, q_prim_vf
61 type(integer_field), dimension(1:num_dims,-1:1), intent(in) :: bc_type
62 logical :: file_exist
63 character(LEN=15) :: fmt
64 character(LEN=3) :: status
65 character(len=int(floor(log10(real(sys_size, wp)))) + 1) :: file_num
66 character(LEN=len_trim(t_step_dir) + name_len) :: file_loc
67 integer :: i, j, k, l, r, c
68 integer :: t_step
69 real(wp), dimension(nb) :: nrtmp
70 real(wp) :: nbub
71 real(wp) :: gamma, pi_inf, qv
72 real(wp) :: rho
73 real(wp) :: pres, t
74 real(wp) :: rhoyks(1:num_species)
75 real(wp) :: pres_mag
76 type(scalar_field), intent(inout), optional :: q_t_sf
77
78 pres_mag = 0._wp
79
80 t = dflt_t_guess
81
82 t_step = 0
83
84 if (old_grid) then
85 status = 'old'
86 else
87 status = 'new'
88 end if
89
90 if (bc_io) then
91 if (igr) then
93 else
94 call s_write_serial_boundary_condition_files(q_prim_vf, bc_type, t_step_dir, old_grid, q_t_sf)
95 end if
96 end if
97
98 file_loc = trim(t_step_dir) // '/x_cb.dat'
99 open (1, file=trim(file_loc), form='unformatted', status=status)
100 write (1) x_cb(-1:m)
101 close (1)
102
103 if (n > 0) then
104 file_loc = trim(t_step_dir) // '/y_cb.dat'
105 open (1, file=trim(file_loc), form='unformatted', status=status)
106 write (1) y_cb(-1:n)
107 close (1)
108
109 if (p > 0) then
110 file_loc = trim(t_step_dir) // '/z_cb.dat'
111 open (1, file=trim(file_loc), form='unformatted', status=status)
112 write (1) z_cb(-1:p)
113 close (1)
114 end if
115 end if
116
117 do i = 1, sys_size
118 write (file_num, '(I0)') i
119 file_loc = trim(t_step_dir) // '/q_cons_vf' // trim(file_num) // '.dat'
120 open (1, file=trim(file_loc), form='unformatted', status=status)
121 write (1) q_cons_vf(i)%sf(0:m,0:n,0:p)
122 close (1)
123 end do
124
125 if (bubbles_lagrange) then
126 block
127 real(stp), allocatable :: beta_ones(:,:,:)
128 character(LEN=len_trim(t_step_dir) + name_len) :: beta_file_loc
129 integer :: jj, kk, ll
130 allocate (beta_ones(0:m,0:n,0:p))
131 do ll = 0, p
132 do kk = 0, n
133 do jj = 0, m
134 beta_ones(jj, kk, ll) = 1.0_stp
135 end do
136 end do
137 end do
138 write (beta_file_loc, '(A,I0,A)') trim(t_step_dir) // '/q_cons_vf', sys_size + 1, '.dat'
139 open (1, file=trim(beta_file_loc), form='unformatted', status=status)
140 write (1) beta_ones
141 close (1)
142 deallocate (beta_ones)
143 end block
144 end if
145
146 if (qbmm .and. .not. polytropic) then
147 do i = 1, nb
148 do r = 1, nnode
149 write (file_num, '(I0)') r + (i - 1)*nnode + sys_size
150 file_loc = trim(t_step_dir) // '/pb' // trim(file_num) // '.dat'
151 open (1, file=trim(file_loc), form='unformatted', status=status)
152 write (1) pb%sf(:,:,:,r, i)
153 close (1)
154 end do
155 end do
156
157 do i = 1, nb
158 do r = 1, nnode
159 write (file_num, '(I0)') r + (i - 1)*nnode + sys_size
160 file_loc = trim(t_step_dir) // '/mv' // trim(file_num) // '.dat'
161 open (1, file=trim(file_loc), form='unformatted', status=status)
162 write (1) mv%sf(:,:,:,r, i)
163 close (1)
164 end do
165 end do
166 end if
167
168 if (precision == precision_single) then
169 fmt = "(2F30.3)"
170 else
171 fmt = "(2F40.14)"
172 end if
173
174 write (t_step_dir, '(A,I0,A,I0)') trim(case_dir) // '/D'
175 file_loc = trim(t_step_dir) // '/.'
176
177 inquire (file=trim(file_loc), exist=file_exist)
178
179 if (.not. file_exist) call s_create_directory(trim(t_step_dir))
180
181 if (cfl_dt) t_step = n_start
182
183 if (n == 0 .and. p == 0) then
184 if (model_eqns == model_eqns_5eq) then
185 do i = 1, sys_size
186 write (file_loc, '(A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/prim.', i, '.', proc_rank, '.', t_step, '.dat'
187
188 open (2, file=trim(file_loc))
189 do j = 0, m
190 if (chemistry) then
191 do c = 1, num_species
192 rhoyks(c) = q_cons_vf(eqn_idx%species%beg + c - 1)%sf(j, 0, 0)
193 end do
194 end if
195
196 call s_convert_to_mixture_variables(q_cons_vf, j, 0, 0, rho, gamma, pi_inf, qv)
197
198 if ((i >= eqn_idx%species%beg) .and. (i <= eqn_idx%species%end)) then
199 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)/rho
200 else if (((i >= eqn_idx%cont%beg) .and. (i <= eqn_idx%cont%end)) .or. ((i >= eqn_idx%adv%beg) &
201 & .and. (i <= eqn_idx%adv%end)) .or. ((i >= eqn_idx%species%beg) .and. (i <= eqn_idx%species%end) &
202 & )) then
203 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)
204 else if (i == eqn_idx%mom%beg) then ! u
205 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%mom%beg)%sf(j, 0, 0)/rho
206 else if (i == eqn_idx%stress%beg) then ! tau_e
207 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%stress%beg)%sf(j, 0, 0)/rho
208 else if (i == eqn_idx%E) then ! p
209 if (mhd) then
210 pres_mag = 0.5_wp*(bx0**2 + q_cons_vf(eqn_idx%B%beg)%sf(j, 0, &
211 & 0)**2 + q_cons_vf(eqn_idx%B%beg + 1)%sf(j, 0, 0)**2)
212 end if
213
214 call s_compute_pressure(q_cons_vf(eqn_idx%E)%sf(j, 0, 0), q_cons_vf(eqn_idx%alf)%sf(j, 0, 0), &
215 & 0.5_wp*(q_cons_vf(eqn_idx%mom%beg)%sf(j, 0, 0)**2._wp)/rho, pi_inf, gamma, &
216 & rho, qv, rhoyks, pres, t, pres_mag=pres_mag)
217 write (2, fmt) x_cb(j), pres
218 else if (mhd) then
219 if (i == eqn_idx%mom%beg + 1) then ! v
220 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%mom%beg + 1)%sf(j, 0, 0)/rho
221 else if (i == eqn_idx%mom%beg + 2) then ! w
222 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%mom%beg + 2)%sf(j, 0, 0)/rho
223 else if (i == eqn_idx%B%beg) then ! By
224 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%B%beg)%sf(j, 0, 0)/rho
225 else if (i == eqn_idx%B%beg + 1) then ! Bz
226 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%B%beg + 1)%sf(j, 0, 0)/rho
227 end if
228 else if ((i >= eqn_idx%bub%beg) .and. (i <= eqn_idx%bub%end) .and. bubbles_euler) then
229 if (qbmm) then
230 nbub = q_cons_vf(eqn_idx%bub%beg)%sf(j, 0, 0)
231 else
232 if (adv_n) then
233 nbub = q_cons_vf(eqn_idx%n)%sf(j, 0, 0)
234 else
235 do k = 1, nb
236 nrtmp(k) = q_cons_vf(qbmm_idx%rs(k))%sf(j, 0, 0)
237 end do
238
239 call s_comp_n_from_cons(real(q_cons_vf(eqn_idx%alf)%sf(j, 0, 0), kind=wp), nrtmp, nbub, weight)
240 end if
241 end if
242 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)/nbub
243 else if (i == eqn_idx%n .and. adv_n .and. bubbles_euler) then
244 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)
245 else if (i == eqn_idx%damage) then
246 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)
247 end if
248 end do
249 close (2)
250 end do
251 end if
252
253 do i = 1, sys_size
254 write (file_loc, '(A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/cons.', i, '.', proc_rank, '.', t_step, '.dat'
255
256 open (2, file=trim(file_loc))
257 do j = 0, m
258 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)
259 end do
260 close (2)
261 end do
262
263 if (qbmm .and. .not. polytropic) then
264 do i = 1, nb
265 do r = 1, nnode
266 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/pres.', i, '.', r, '.', proc_rank, &
267 & '.', t_step, '.dat'
268
269 open (2, file=trim(file_loc))
270 do j = 0, m
271 write (2, fmt) x_cb(j), pb%sf(j, 0, 0, r, i)
272 end do
273 close (2)
274 end do
275 end do
276 do i = 1, nb
277 do r = 1, nnode
278 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/mv.', i, '.', r, '.', proc_rank, &
279 & '.', t_step, '.dat'
280
281 open (2, file=trim(file_loc))
282 do j = 0, m
283 write (2, fmt) x_cb(j), mv%sf(j, 0, 0, r, i)
284 end do
285 close (2)
286 end do
287 end do
288 end if
289 end if
290
291 if (precision == precision_single) then
292 fmt = "(3F30.7)"
293 else
294 fmt = "(3F40.14)"
295 end if
296
297 if ((n > 0) .and. (p == 0)) then
298 do i = 1, sys_size
299 write (file_loc, '(A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/cons.', i, '.', proc_rank, '.', t_step, '.dat'
300 open (2, file=trim(file_loc))
301 do j = 0, m
302 do k = 0, n
303 write (2, fmt) x_cb(j), y_cb(k), q_cons_vf(i)%sf(j, k, 0)
304 end do
305 write (2, *)
306 end do
307 close (2)
308 end do
309
310 if (qbmm .and. .not. polytropic) then
311 do i = 1, nb
312 do r = 1, nnode
313 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/pres.', i, '.', r, '.', proc_rank, &
314 & '.', t_step, '.dat'
315
316 open (2, file=trim(file_loc))
317 do j = 0, m
318 do k = 0, n
319 write (2, fmt) x_cb(j), y_cb(k), pb%sf(j, k, 0, r, i)
320 end do
321 end do
322 close (2)
323 end do
324 end do
325 do i = 1, nb
326 do r = 1, nnode
327 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/mv.', i, '.', r, '.', proc_rank, &
328 & '.', t_step, '.dat'
329
330 open (2, file=trim(file_loc))
331 do j = 0, m
332 do k = 0, n
333 write (2, fmt) x_cb(j), y_cb(k), mv%sf(j, k, 0, r, i)
334 end do
335 end do
336 close (2)
337 end do
338 end do
339 end if
340 end if
341
342 if (precision == precision_single) then
343 fmt = "(4F30.7)"
344 else
345 fmt = "(4F40.14)"
346 end if
347
348 if (p > 0) then
349 do i = 1, sys_size
350 write (file_loc, '(A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/cons.', i, '.', proc_rank, '.', t_step, '.dat'
351 open (2, file=trim(file_loc))
352 do j = 0, m
353 do k = 0, n
354 do l = 0, p
355 write (2, fmt) x_cb(j), y_cb(k), z_cb(l), q_cons_vf(i)%sf(j, k, l)
356 end do
357 write (2, *)
358 end do
359 write (2, *)
360 end do
361 close (2)
362 end do
363
364 if (qbmm .and. .not. polytropic) then
365 do i = 1, nb
366 do r = 1, nnode
367 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/pres.', i, '.', r, '.', proc_rank, &
368 & '.', t_step, '.dat'
369
370 open (2, file=trim(file_loc))
371 do j = 0, m
372 do k = 0, n
373 do l = 0, p
374 write (2, fmt) x_cb(j), y_cb(k), z_cb(l), pb%sf(j, k, l, r, i)
375 end do
376 end do
377 end do
378 close (2)
379 end do
380 end do
381 do i = 1, nb
382 do r = 1, nnode
383 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/mv.', i, '.', r, '.', proc_rank, &
384 & '.', t_step, '.dat'
385
386 open (2, file=trim(file_loc))
387 do j = 0, m
388 do k = 0, n
389 do l = 0, p
390 write (2, fmt) x_cb(j), y_cb(k), z_cb(l), mv%sf(j, k, l, r, i)
391 end do
392 end do
393 end do
394 close (2)
395 end do
396 end do
397 end if
398 end if
399
400 end subroutine s_write_serial_data_files
401
402 !> Writes grid and initial condition data files in parallel to the "0" time-step directory in the local processor rank folder
403 impure subroutine s_write_parallel_data_files(q_cons_vf, q_prim_vf, bc_type, q_T_sf)
404
405 type(scalar_field), dimension(sys_size), intent(inout) :: q_cons_vf, q_prim_vf
406 type(integer_field), dimension(1:num_dims,-1:1), intent(in) :: bc_type
407 type(scalar_field), optional, intent(inout) :: q_t_sf
408
409#ifdef MFC_MPI
410 integer :: ifile, ierr, data_size
411 integer, dimension(MPI_STATUS_SIZE) :: status
412 integer(KIND=MPI_OFFSET_KIND) :: disp
413 integer(KIND=MPI_OFFSET_KIND) :: m_mok, n_mok, p_mok
414 integer(KIND=MPI_OFFSET_KIND) :: wp_mok, var_mok, str_mok
415 integer(KIND=MPI_OFFSET_KIND) :: nvars_mok
416 integer(KIND=MPI_OFFSET_KIND) :: mok
417 character(LEN=path_len + 2*name_len) :: file_loc
418 logical :: file_exist, dir_check
419 integer :: i, j, k, l
420 real(wp) :: loc_violations, glb_violations
421 integer :: m_ds, n_ds, p_ds
422 integer :: m_glb_ds, n_glb_ds, p_glb_ds
423 integer :: m_glb_save, n_glb_save, p_glb_save !< Size of array being saved
424
425 loc_violations = 0._wp
426
427 if (down_sample) then
428 if ((mod(m + 1, 3) > 0) .or. (mod(n + 1, 3) > 0) .or. (mod(p + 1, 3) > 0)) then
429 loc_violations = 1._wp
430 end if
431 call s_mpi_allreduce_sum(loc_violations, glb_violations)
432 if (proc_rank == 0 .and. nint(glb_violations) > 0) then
433 print *, &
434 & "WARNING: Attempting to downsample data but there are" &
435 & // "processors with local problem sizes that are not divisible by 3."
436 end if
437 call s_populate_variables_buffers(bc_type, q_cons_vf)
438 call s_downsample_data(q_cons_vf, q_cons_temp, m_ds, n_ds, p_ds, m_glb_ds, n_glb_ds, p_glb_ds)
439 end if
440
441 if (file_per_process) then
442 if (proc_rank == 0) then
443 file_loc = trim(case_dir) // '/restart_data/lustre_0'
444 call my_inquire(file_loc, dir_check)
445 if (dir_check .neqv. .true.) then
446 call s_create_directory(trim(file_loc))
447 end if
448 call s_create_directory(trim(file_loc))
449 end if
450 call s_mpi_barrier()
451 call s_delay_file_access(proc_rank)
452
453 if (down_sample) then
454 call s_initialize_mpi_data_ds(m_ds, n_ds, p_ds)
455 else
456 call s_initialize_mpi_data(q_cons_vf, qbmm_pb=pb, qbmm_mv=mv)
457 end if
458
459 if (cfl_dt) then
460 write (file_loc, '(I0,A,i7.7,A)') n_start, '_', proc_rank, '.dat'
461 else
462 write (file_loc, '(I0,A,i7.7,A)') t_step_start, '_', proc_rank, '.dat'
463 end if
464 file_loc = trim(restart_dir) // '/lustre_0' // trim(mpiiofs) // trim(file_loc)
465 inquire (file=trim(file_loc), exist=file_exist)
466 if (file_exist .and. proc_rank == 0) then
467 call mpi_file_delete(file_loc, mpi_info_int, ierr)
468 end if
469 if (file_exist) call mpi_file_delete(file_loc, mpi_info_int, ierr)
470 call mpi_file_open(mpi_comm_self, file_loc, ior(mpi_mode_wronly, mpi_mode_create), mpi_info_int, ifile, ierr)
471
472 if (down_sample) then
473 data_size = (m_ds + 3)*(n_ds + 3)*(p_ds + 3)
474 m_glb_save = m_glb_ds + 3
475 n_glb_save = n_glb_ds + 3
476 p_glb_save = p_glb_ds + 3
477 else
478 data_size = (m + 1)*(n + 1)*(p + 1)
479 m_glb_save = m_glb + 1
480 n_glb_save = n_glb + 1
481 p_glb_save = p_glb + 1
482 end if
483
484 ! Resize some integers so MPI can write even the biggest files
485 m_mok = int(m_glb_save, mpi_offset_kind)
486 n_mok = int(n_glb_save, mpi_offset_kind)
487 p_mok = int(p_glb_save, mpi_offset_kind)
488 wp_mok = int(storage_size(0._stp)/8, mpi_offset_kind)
489 mok = int(1._wp, mpi_offset_kind)
490 str_mok = int(name_len, mpi_offset_kind)
491 nvars_mok = int(sys_size, mpi_offset_kind)
492
493 if (bubbles_euler) then
494 do i = 1, sys_size
495 var_mok = int(i, mpi_offset_kind)
496
497 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
498 end do
499 if (qbmm .and. .not. polytropic) then
500 do i = sys_size + 1, sys_size + 2*nb*nnode
501 var_mok = int(i, mpi_offset_kind)
502
503 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
504 end do
505 end if
506 else
507 if (down_sample) then
508 do i = 1, sys_size
509 var_mok = int(i, mpi_offset_kind)
510
511 call mpi_file_write_all(ifile, q_cons_temp(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
512 end do
513 else
514 do i = 1, sys_size
515 var_mok = int(i, mpi_offset_kind)
516
517 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
518 end do
519 end if
520 end if
521
522 if (bubbles_lagrange) then
523 block
524 real(stp), allocatable :: beta_ones(:,:,:)
525 integer :: jj, kk, ll
526 allocate (beta_ones(0:m,0:n,0:p))
527 do ll = 0, p
528 do kk = 0, n
529 do jj = 0, m
530 beta_ones(jj, kk, ll) = 1.0_stp
531 end do
532 end do
533 end do
534 call mpi_file_write_all(ifile, beta_ones, data_size*mpi_io_type, mpi_io_p, status, ierr)
535 deallocate (beta_ones)
536 end block
537 end if
538
539 call mpi_file_close(ifile, ierr)
540 else
541 call s_initialize_mpi_data(q_cons_vf, qbmm_pb=pb, qbmm_mv=mv)
542
543 if (cfl_dt) then
544 write (file_loc, '(I0,A)') n_start, '.dat'
545 else
546 write (file_loc, '(I0,A)') t_step_start, '.dat'
547 end if
548 file_loc = trim(restart_dir) // trim(mpiiofs) // trim(file_loc)
549 inquire (file=trim(file_loc), exist=file_exist)
550 if (file_exist .and. proc_rank == 0) then
551 call mpi_file_delete(file_loc, mpi_info_int, ierr)
552 end if
553 call mpi_file_open(mpi_comm_world, file_loc, ior(mpi_mode_wronly, mpi_mode_create), mpi_info_int, ifile, ierr)
554
555 data_size = (m + 1)*(n + 1)*(p + 1)
556
557 ! Resize some integers so MPI can write even the biggest files
558 m_mok = int(m_glb + 1, mpi_offset_kind)
559 n_mok = int(n_glb + 1, mpi_offset_kind)
560 p_mok = int(p_glb + 1, mpi_offset_kind)
561 wp_mok = int(storage_size(0._stp)/8, mpi_offset_kind)
562 mok = int(1._wp, mpi_offset_kind)
563 str_mok = int(name_len, mpi_offset_kind)
564 nvars_mok = int(sys_size, mpi_offset_kind)
565
566 if (bubbles_euler) then
567 do i = 1, sys_size
568 var_mok = int(i, mpi_offset_kind)
569
570 disp = m_mok*max(mok, n_mok)*max(mok, p_mok)*wp_mok*(var_mok - 1)
571
572 call mpi_file_set_view(ifile, disp, mpi_io_p, mpi_io_data%view(i), 'native', mpi_info_int, ierr)
573 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
574 end do
575 if (qbmm .and. .not. polytropic) then
576 do i = sys_size + 1, sys_size + 2*nb*nnode
577 var_mok = int(i, mpi_offset_kind)
578
579 disp = m_mok*max(mok, n_mok)*max(mok, p_mok)*wp_mok*(var_mok - 1)
580
581 call mpi_file_set_view(ifile, disp, mpi_io_p, mpi_io_data%view(i), 'native', mpi_info_int, ierr)
582 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
583 end do
584 end if
585 else
586 do i = 1, sys_size
587 var_mok = int(i, mpi_offset_kind)
588
589 disp = m_mok*max(mok, n_mok)*max(mok, p_mok)*wp_mok*(var_mok - 1)
590
591 call mpi_file_set_view(ifile, disp, mpi_io_p, mpi_io_data%view(i), 'native', mpi_info_int, ierr)
592 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
593 end do
594 end if
595
596 if (bubbles_lagrange) then
597 block
598 real(stp), allocatable :: beta_ones(:,:,:)
599 integer :: jj, kk, ll
600 allocate (beta_ones(0:m,0:n,0:p))
601 do ll = 0, p
602 do kk = 0, n
603 do jj = 0, m
604 beta_ones(jj, kk, ll) = 1.0_stp
605 end do
606 end do
607 end do
608 var_mok = int(sys_size + 1, mpi_offset_kind)
609 disp = m_mok*max(mok, n_mok)*max(mok, p_mok)*wp_mok*(var_mok - 1)
610 call mpi_file_set_view(ifile, disp, mpi_io_p, mpi_io_data%view(1), 'native', mpi_info_int, ierr)
611 call mpi_file_write_all(ifile, beta_ones, data_size*mpi_io_type, mpi_io_p, status, ierr)
612 deallocate (beta_ones)
613 end block
614 end if
615
616 call mpi_file_close(ifile, ierr)
617 end if
618#endif
619
620 if (bc_io) then
621 if (igr) then
622 call s_write_parallel_boundary_condition_files(q_cons_vf, bc_type)
623 else
624 call s_write_parallel_boundary_condition_files(q_prim_vf, bc_type, q_t_sf)
625 end if
626 end if
627
628 end subroutine s_write_parallel_data_files
629
630 !> Computation of parameters, allocation procedures, and/or any other tasks needed to properly setup the module
632
633 character(LEN=len_trim(case_dir) + 2*name_len) :: file_loc
634 character(len=15) :: temp
635 character(LEN=1), dimension(3), parameter :: coord = (/'x', 'y', 'z'/)
636 logical :: dir_check
637 integer :: i, iu
638 integer :: m_ds, n_ds, p_ds
639
640 if (parallel_io .neqv. .true.) then
641 write (t_step_dir, '(A,I0,A)') '/p_all/p', proc_rank, '/0'
642 t_step_dir = trim(case_dir) // trim(t_step_dir)
643
644 if (old_grid .neqv. .true.) then
645 file_loc = trim(t_step_dir) // '/'
646
647 call my_inquire(file_loc, dir_check)
648
649 if (dir_check) call s_delete_directory(trim(t_step_dir))
650
651 call s_create_directory(trim(t_step_dir))
652 end if
653
655 else
656 write (restart_dir, '(A)') '/restart_data'
657 restart_dir = trim(case_dir) // trim(restart_dir)
658
659 if ((old_grid .neqv. .true.) .and. (proc_rank == 0)) then
660 file_loc = trim(restart_dir) // '/'
661 call my_inquire(file_loc, dir_check)
662
663 if (dir_check) call s_delete_directory(trim(restart_dir))
664 call s_create_directory(trim(restart_dir))
665 end if
666
667 call s_mpi_barrier()
668
670 end if
671
672 open (newunit=iu, file='indices.dat', status='unknown')
673
674 write (iu, '(A)') "Warning: The creation of file is currently experimental."
675 write (iu, '(A)') "This file may contain errors and not support all features."
676
677 write (iu, '(A3,A20,A20)') "#", "Conservative", "Primitive"
678 write (iu, '(A)') " "
679 do i = eqn_idx%cont%beg, eqn_idx%cont%end
680 write (temp, '(I0)') i - eqn_idx%cont%beg + 1
681 write (iu, '(I3,A20,A20)') i, "\alpha_{" // trim(temp) // "} \rho_{" // trim(temp) // "}", &
682 & "\alpha_{" // trim(temp) // "} \rho"
683 end do
684 do i = eqn_idx%mom%beg, eqn_idx%mom%end
685 write (iu, '(I3,A20,A20)') i, "\rho u_" // coord(i - eqn_idx%mom%beg + 1), "u_" // coord(i - eqn_idx%mom%beg + 1)
686 end do
687 if (eqn_idx%E /= 0) write (iu, '(I3,A20,A20)') eqn_idx%E, "\rho U", "p"
688 do i = eqn_idx%adv%beg, eqn_idx%adv%end
689 write (temp, '(I0)') i - eqn_idx%cont%beg + 1
690 write (iu, '(I3,A20,A20)') i, "\alpha_{" // trim(temp) // "}", "\alpha_{" // trim(temp) // "}"
691 end do
692 if (chemistry) then
693 do i = 1, num_species
694 write (iu, '(I3,A20,A20)') eqn_idx%species%beg + i - 1, "Y_{" // trim(species_names(i)) // "} \rho", &
695 & "Y_{" // trim(species_names(i)) // "}"
696 end do
697 end if
698
699 write (iu, '(A)') ""
700 call write_range(eqn_idx%cont%beg, eqn_idx%cont%end, " Continuity")
701 call write_range(eqn_idx%mom%beg, eqn_idx%mom%end, " Momentum")
702 call write_range(eqn_idx%E, eqn_idx%E, " Energy/Pressure")
703 call write_range(eqn_idx%adv%beg, eqn_idx%adv%end, " Advection")
704 call write_range(eqn_idx%bub%beg, eqn_idx%bub%end, " Bubbles")
705 call write_range(eqn_idx%stress%beg, eqn_idx%stress%end, " Stress")
706 call write_range(eqn_idx%int_en%beg, eqn_idx%int_en%end, " Internal Energies")
707 call write_range(eqn_idx%B%beg, eqn_idx%B%end, " Magnetic Field")
708 call write_range(eqn_idx%c, eqn_idx%c, " Color Function")
709 call write_range(eqn_idx%species%beg, eqn_idx%species%end, " Chemistry")
710
711 close (iu)
712
713 if (down_sample) then
714 m_ds = int((m + 1)/3) - 1
715 n_ds = int((n + 1)/3) - 1
716 p_ds = int((p + 1)/3) - 1
717
718 allocate (q_cons_temp(1:sys_size))
719 do i = 1, sys_size
720 allocate (q_cons_temp(i)%sf(-1:m_ds + 1,-1:n_ds + 1,-1:p_ds + 1))
721 end do
722 end if
723
724 contains
725
726 subroutine write_range(beg, end, label)
727
728 integer, intent(in) :: beg, end
729 character(*), intent(in) :: label
730
731 if (beg /= 0) write (iu, '("[",I0,",",I0,"]",A)') beg, end, label
732
733 end subroutine write_range
734
736
737 !> @brief Writes the initial IB layout (namelist patch_ib entries, then generated particle-cloud beds) that simulation reads
738 !! back at startup (s_read_ib_restart_data, src/simulation/m_start_up.fpp), in the layouts simulation's own IB state writers
739 !! use. Under file_per_process each rank writes only the IBs it owns to restart_data/lustre_0/ib_state_0_<rank>.dat; otherwise
740 !! only rank 0 calls this and writes every IB, in global-id order, to restart_data/ib_state_0.dat.
741 impure subroutine s_write_ib_state_0_file(glb_bounds, particle_cloud_ibs, num_particle_cloud_ibs)
742
743 type(bounds_info), dimension(3), intent(in) :: glb_bounds
744 type(ib_patch_parameters), dimension(:), intent(in) :: particle_cloud_ibs
745 integer, intent(in) :: num_particle_cloud_ibs
746 character(LEN=len_trim(case_dir) + 2*name_len) :: file_loc
747 integer :: i, ios, file_unit
748 logical, dimension(num_ibs) :: owned
749 real(wp), dimension(3) :: centroid
750
751 if (file_per_process) then
752 do i = 1, num_ibs
753 centroid = [patch_ib(i)%x_centroid, patch_ib(i)%y_centroid, patch_ib(i)%z_centroid]
754 owned(i) = f_local_rank_owns_location(centroid, glb_bounds)
755 end do
756
757 if (proc_rank == 0) call s_create_directory(trim(case_dir) // '/restart_data/lustre_0')
758 call s_mpi_barrier()
759 call s_delay_file_access(proc_rank)
760 write (file_loc, '(A,i7.7,A)') '/restart_data/lustre_0/ib_state_0_', proc_rank, '.dat'
761 else
762 owned = .true.
763 call s_create_directory(trim(case_dir) // '/restart_data')
764 file_loc = '/restart_data/ib_state_0.dat'
765 end if
766 file_loc = trim(case_dir) // trim(file_loc)
767
768 open (newunit=file_unit, file=trim(file_loc), form='unformatted', access='stream', status='replace', iostat=ios)
769 if (ios /= 0) call s_mpi_abort('Cannot open IB state output file: ' // trim(file_loc))
770
771 if (file_per_process) write (file_unit) count(owned) + num_particle_cloud_ibs
772 do i = 1, num_ibs
773 if (owned(i)) call s_write_ib_state_record(patch_ib(i), i)
774 end do
775 do i = 1, num_particle_cloud_ibs
776 call s_write_ib_state_record(particle_cloud_ibs(i), particle_cloud_ibs(i)%gbl_patch_id)
777 end do
778
779 close (file_unit)
780
781 contains
782
783 !> Writes one 20-field IB state record, prefixed by its global id under file_per_process.
784 subroutine s_write_ib_state_record(ib_patch, gbl_id)
785
786 type(ib_patch_parameters), intent(in) :: ib_patch
787 integer, intent(in) :: gbl_id
788 real(wp), dimension(20) :: ib_buf
789
790 ib_buf = 0._wp
791 ib_buf(8:10) = ib_patch%vel
792 ib_buf(11:13) = ib_patch%angular_vel
793 ib_buf(14:16) = ib_patch%angles
794 ib_buf(17) = ib_patch%x_centroid
795 ib_buf(18) = ib_patch%y_centroid
796 ib_buf(19) = ib_patch%z_centroid
797 ib_buf(20) = ib_patch%radius
798
799 if (file_per_process) write (file_unit) gbl_id
800 write (file_unit) ib_buf
801
802 end subroutine s_write_ib_state_record
803
804 end subroutine s_write_ib_state_0_file
805
806 !> Resets s_write_data_files pointer
808
809 integer :: i
810
811 s_write_data_files => null()
812
813 if (down_sample) then
814 do i = 1, sys_size
815 deallocate (q_cons_temp(i)%sf)
816 end do
817 deallocate (q_cons_temp)
818 end if
819
820 end subroutine s_finalize_data_output_module
821
822end module m_data_output
Interface for the conservative data.
subroutine s_write_ib_state_record(ib_patch, gbl_id)
Writes one 20-field IB state record, prefixed by its global id under file_per_process.
subroutine write_range(beg, end, label)
type(scalar_field), dimension(sys_size), intent(inout) q_cons_vf
integer, intent(in) k
integer, intent(in) j
integer, intent(in) l
Noncharacteristic and processor boundary condition application for ghost cells and buffer regions.
Applies spatially varying boundary condition patches along domain edges and faces.
Boundary condition restart I/O, capillary/IGR buffer population, and grid-variable buffers.
subroutine s_write_serial_boundary_condition_files(q_prim_vf, bc_type, step_dirpath, old_grid_in, q_t_sf)
Write boundary condition type and buffer data to serial (unformatted) restart files.
Platform-specific file and directory operations: create, delete, inquire, getcwd, and basename.
impure subroutine s_create_directory(dir_name)
Create a directory and all its parents if it does not exist.
Compile-time constant parameters: default values, tolerances, and physical constants.
integer, parameter model_eqns_5eq
real(wp), parameter dflt_t_guess
Default guess for temperature (when a previous value is not available).
integer, parameter nnode
Number of QBMM nodes.
integer, parameter precision_single
Writes grid and initial condition data to serial or parallel output files.
type(scalar_field), dimension(:), allocatable q_cons_temp
procedure(s_write_abstract_data_files), pointer, public s_write_data_files
impure subroutine, public s_write_ib_state_0_file(glb_bounds, particle_cloud_ibs, num_particle_cloud_ibs)
Writes the initial IB layout (namelist patch_ib entries, then generated particle-cloud beds) that sim...
impure subroutine, public s_write_serial_data_files(q_cons_vf, q_prim_vf, bc_type, q_t_sf)
Writes grid and initial condition data files to the "0" time-step directory in the local processor ra...
character(len=path_len+2 *name_len), private t_step_dir
Time-step folder into which grid and initial condition data will be placed.
impure subroutine, public s_initialize_data_output_module
Computation of parameters, allocation procedures, and/or any other tasks needed to properly setup the...
impure subroutine, public s_finalize_data_output_module
Resets s_write_data_files pointer.
impure subroutine, public s_write_parallel_data_files(q_cons_vf, q_prim_vf, bc_type, q_t_sf)
Writes grid and initial condition data files in parallel to the "0" time-step directory in the local ...
character(len=path_len+2 *name_len), public restart_dir
Restart data folder.
Rank-staggered file access delays to prevent I/O contention on parallel file systems.
Shared derived types for field data, patch geometry, bubble dynamics, and MPI I/O structures.
Defines global parameters for the computational domain, simulation algorithm, and initial conditions.
type(qbmm_idx_info) qbmm_idx
QBMM moment index mappings.
integer proc_rank
Rank of the local processor Number of cells in the x-, y- and z-coordinate directions.
logical bc_io
whether or not to save BC data
real(wp), dimension(:), allocatable y_cb
real(wp), dimension(:), allocatable weight
real(wp), dimension(:), allocatable z_cb
real(wp), dimension(:), allocatable x_cb
Locations of cell-boundaries (cb) in x-, y- and z-directions, respectively.
Utility routines for bubble model setup, coordinate transforms, array sampling, and special functions...
subroutine, public s_comp_n_from_cons(vftmp, nrtmp, ntmp, weights)
Compute the bubble number density from the conservative void fraction and weighted bubble radii.
Broadcasts user inputs and decomposes the domain across MPI ranks for pre-processing.
Conservative-to-primitive variable conversion, mixture property evaluation, and pressure computation.
subroutine, public s_compute_pressure(energy, alf, dyn_p, pi_inf, gamma, rho, qv, rhoyks, pres, t, e_e_in, pres_mag)
Compute the pressure from the appropriate equation of state.
subroutine, public s_convert_to_mixture_variables(q_vf, i, j, k, rho, gamma, pi_inf, qv, re_k, g_k, g)
Dispatch to the s_convert_mixture_to_mixture_variables and s_convert_species_to_mixture_variables sub...
Derived type annexing an integer scalar field (SF).
Derived type for bubble variables pb and mv at quadrature nodes (qbmm).
Derived type annexing a scalar field (SF).