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, lit_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 gamma = gammas(1)
169 lit_gamma = gs_min(1)
170 pi_inf = pi_infs(1)
171 qv = qvs(1)
172
173 if (precision == precision_single) then
174 fmt = "(2F30.3)"
175 else
176 fmt = "(2F40.14)"
177 end if
178
179 write (t_step_dir, '(A,I0,A,I0)') trim(case_dir) // '/D'
180 file_loc = trim(t_step_dir) // '/.'
181
182 inquire (file=trim(file_loc), exist=file_exist)
183
184 if (.not. file_exist) call s_create_directory(trim(t_step_dir))
185
186 if (cfl_dt) t_step = n_start
187
188 if (n == 0 .and. p == 0) then
189 if (model_eqns == model_eqns_5eq) then
190 do i = 1, sys_size
191 write (file_loc, '(A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/prim.', i, '.', proc_rank, '.', t_step, '.dat'
192
193 open (2, file=trim(file_loc))
194 do j = 0, m
195 if (chemistry) then
196 do c = 1, num_species
197 rhoyks(c) = q_cons_vf(eqn_idx%species%beg + c - 1)%sf(j, 0, 0)
198 end do
199 end if
200
201 call s_convert_to_mixture_variables(q_cons_vf, j, 0, 0, rho, gamma, pi_inf, qv)
202
203 lit_gamma = 1._wp/gamma + 1._wp
204
205 if ((i >= eqn_idx%species%beg) .and. (i <= eqn_idx%species%end)) then
206 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)/rho
207 else if (((i >= eqn_idx%cont%beg) .and. (i <= eqn_idx%cont%end)) .or. ((i >= eqn_idx%adv%beg) &
208 & .and. (i <= eqn_idx%adv%end)) .or. ((i >= eqn_idx%species%beg) .and. (i <= eqn_idx%species%end) &
209 & )) then
210 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)
211 else if (i == eqn_idx%mom%beg) then ! u
212 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%mom%beg)%sf(j, 0, 0)/rho
213 else if (i == eqn_idx%stress%beg) then ! tau_e
214 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%stress%beg)%sf(j, 0, 0)/rho
215 else if (i == eqn_idx%E) then ! p
216 if (mhd) then
217 pres_mag = 0.5_wp*(bx0**2 + q_cons_vf(eqn_idx%B%beg)%sf(j, 0, &
218 & 0)**2 + q_cons_vf(eqn_idx%B%beg + 1)%sf(j, 0, 0)**2)
219 end if
220
221 call s_compute_pressure(q_cons_vf(eqn_idx%E)%sf(j, 0, 0), q_cons_vf(eqn_idx%alf)%sf(j, 0, 0), &
222 & 0.5_wp*(q_cons_vf(eqn_idx%mom%beg)%sf(j, 0, 0)**2._wp)/rho, pi_inf, gamma, &
223 & rho, qv, rhoyks, pres, t, pres_mag=pres_mag)
224 write (2, fmt) x_cb(j), pres
225 else if (mhd) then
226 if (i == eqn_idx%mom%beg + 1) then ! v
227 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%mom%beg + 1)%sf(j, 0, 0)/rho
228 else if (i == eqn_idx%mom%beg + 2) then ! w
229 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%mom%beg + 2)%sf(j, 0, 0)/rho
230 else if (i == eqn_idx%B%beg) then ! By
231 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%B%beg)%sf(j, 0, 0)/rho
232 else if (i == eqn_idx%B%beg + 1) then ! Bz
233 write (2, fmt) x_cb(j), q_cons_vf(eqn_idx%B%beg + 1)%sf(j, 0, 0)/rho
234 end if
235 else if ((i >= eqn_idx%bub%beg) .and. (i <= eqn_idx%bub%end) .and. bubbles_euler) then
236 if (qbmm) then
237 nbub = q_cons_vf(eqn_idx%bub%beg)%sf(j, 0, 0)
238 else
239 if (adv_n) then
240 nbub = q_cons_vf(eqn_idx%n)%sf(j, 0, 0)
241 else
242 do k = 1, nb
243 nrtmp(k) = q_cons_vf(qbmm_idx%rs(k))%sf(j, 0, 0)
244 end do
245
246 call s_comp_n_from_cons(real(q_cons_vf(eqn_idx%alf)%sf(j, 0, 0), kind=wp), nrtmp, nbub, weight)
247 end if
248 end if
249 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)/nbub
250 else if (i == eqn_idx%n .and. adv_n .and. bubbles_euler) then
251 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)
252 else if (i == eqn_idx%damage) then
253 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)
254 end if
255 end do
256 close (2)
257 end do
258 end if
259
260 do i = 1, sys_size
261 write (file_loc, '(A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/cons.', i, '.', proc_rank, '.', t_step, '.dat'
262
263 open (2, file=trim(file_loc))
264 do j = 0, m
265 write (2, fmt) x_cb(j), q_cons_vf(i)%sf(j, 0, 0)
266 end do
267 close (2)
268 end do
269
270 if (qbmm .and. .not. polytropic) then
271 do i = 1, nb
272 do r = 1, nnode
273 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/pres.', i, '.', r, '.', proc_rank, &
274 & '.', t_step, '.dat'
275
276 open (2, file=trim(file_loc))
277 do j = 0, m
278 write (2, fmt) x_cb(j), pb%sf(j, 0, 0, r, i)
279 end do
280 close (2)
281 end do
282 end do
283 do i = 1, nb
284 do r = 1, nnode
285 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/mv.', i, '.', r, '.', proc_rank, &
286 & '.', t_step, '.dat'
287
288 open (2, file=trim(file_loc))
289 do j = 0, m
290 write (2, fmt) x_cb(j), mv%sf(j, 0, 0, r, i)
291 end do
292 close (2)
293 end do
294 end do
295 end if
296 end if
297
298 if (precision == precision_single) then
299 fmt = "(3F30.7)"
300 else
301 fmt = "(3F40.14)"
302 end if
303
304 if ((n > 0) .and. (p == 0)) then
305 do i = 1, sys_size
306 write (file_loc, '(A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/cons.', i, '.', proc_rank, '.', t_step, '.dat'
307 open (2, file=trim(file_loc))
308 do j = 0, m
309 do k = 0, n
310 write (2, fmt) x_cb(j), y_cb(k), q_cons_vf(i)%sf(j, k, 0)
311 end do
312 write (2, *)
313 end do
314 close (2)
315 end do
316
317 if (qbmm .and. .not. polytropic) then
318 do i = 1, nb
319 do r = 1, nnode
320 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/pres.', i, '.', r, '.', proc_rank, &
321 & '.', t_step, '.dat'
322
323 open (2, file=trim(file_loc))
324 do j = 0, m
325 do k = 0, n
326 write (2, fmt) x_cb(j), y_cb(k), pb%sf(j, k, 0, r, i)
327 end do
328 end do
329 close (2)
330 end do
331 end do
332 do i = 1, nb
333 do r = 1, nnode
334 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/mv.', i, '.', r, '.', proc_rank, &
335 & '.', t_step, '.dat'
336
337 open (2, file=trim(file_loc))
338 do j = 0, m
339 do k = 0, n
340 write (2, fmt) x_cb(j), y_cb(k), mv%sf(j, k, 0, r, i)
341 end do
342 end do
343 close (2)
344 end do
345 end do
346 end if
347 end if
348
349 if (precision == precision_single) then
350 fmt = "(4F30.7)"
351 else
352 fmt = "(4F40.14)"
353 end if
354
355 if (p > 0) then
356 do i = 1, sys_size
357 write (file_loc, '(A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/cons.', i, '.', proc_rank, '.', t_step, '.dat'
358 open (2, file=trim(file_loc))
359 do j = 0, m
360 do k = 0, n
361 do l = 0, p
362 write (2, fmt) x_cb(j), y_cb(k), z_cb(l), q_cons_vf(i)%sf(j, k, l)
363 end do
364 write (2, *)
365 end do
366 write (2, *)
367 end do
368 close (2)
369 end do
370
371 if (qbmm .and. .not. polytropic) then
372 do i = 1, nb
373 do r = 1, nnode
374 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/pres.', i, '.', r, '.', proc_rank, &
375 & '.', t_step, '.dat'
376
377 open (2, file=trim(file_loc))
378 do j = 0, m
379 do k = 0, n
380 do l = 0, p
381 write (2, fmt) x_cb(j), y_cb(k), z_cb(l), pb%sf(j, k, l, r, i)
382 end do
383 end do
384 end do
385 close (2)
386 end do
387 end do
388 do i = 1, nb
389 do r = 1, nnode
390 write (file_loc, '(A,I0,A,I0,A,I2.2,A,I6.6,A)') trim(t_step_dir) // '/mv.', i, '.', r, '.', proc_rank, &
391 & '.', t_step, '.dat'
392
393 open (2, file=trim(file_loc))
394 do j = 0, m
395 do k = 0, n
396 do l = 0, p
397 write (2, fmt) x_cb(j), y_cb(k), z_cb(l), mv%sf(j, k, l, r, i)
398 end do
399 end do
400 end do
401 close (2)
402 end do
403 end do
404 end if
405 end if
406
407 end subroutine s_write_serial_data_files
408
409 !> Writes grid and initial condition data files in parallel to the "0" time-step directory in the local processor rank folder
410 impure subroutine s_write_parallel_data_files(q_cons_vf, q_prim_vf, bc_type, q_T_sf)
411
412 type(scalar_field), dimension(sys_size), intent(inout) :: q_cons_vf, q_prim_vf
413 type(integer_field), dimension(1:num_dims,-1:1), intent(in) :: bc_type
414 type(scalar_field), optional, intent(inout) :: q_t_sf
415
416#ifdef MFC_MPI
417 integer :: ifile, ierr, data_size
418 integer, dimension(MPI_STATUS_SIZE) :: status
419 integer(KIND=MPI_OFFSET_KIND) :: disp
420 integer(KIND=MPI_OFFSET_KIND) :: m_mok, n_mok, p_mok
421 integer(KIND=MPI_OFFSET_KIND) :: wp_mok, var_mok, str_mok
422 integer(KIND=MPI_OFFSET_KIND) :: nvars_mok
423 integer(KIND=MPI_OFFSET_KIND) :: mok
424 character(LEN=path_len + 2*name_len) :: file_loc
425 logical :: file_exist, dir_check
426 integer :: i, j, k, l
427 real(wp) :: loc_violations, glb_violations
428 integer :: m_ds, n_ds, p_ds
429 integer :: m_glb_ds, n_glb_ds, p_glb_ds
430 integer :: m_glb_save, n_glb_save, p_glb_save !< Size of array being saved
431
432 loc_violations = 0._wp
433
434 if (down_sample) then
435 if ((mod(m + 1, 3) > 0) .or. (mod(n + 1, 3) > 0) .or. (mod(p + 1, 3) > 0)) then
436 loc_violations = 1._wp
437 end if
438 call s_mpi_allreduce_sum(loc_violations, glb_violations)
439 if (proc_rank == 0 .and. nint(glb_violations) > 0) then
440 print *, &
441 & "WARNING: Attempting to downsample data but there are" &
442 & // "processors with local problem sizes that are not divisible by 3."
443 end if
444 call s_populate_variables_buffers(bc_type, q_cons_vf)
445 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)
446 end if
447
448 if (file_per_process) then
449 if (proc_rank == 0) then
450 file_loc = trim(case_dir) // '/restart_data/lustre_0'
451 call my_inquire(file_loc, dir_check)
452 if (dir_check .neqv. .true.) then
453 call s_create_directory(trim(file_loc))
454 end if
455 call s_create_directory(trim(file_loc))
456 end if
457 call s_mpi_barrier()
458 call delayfileaccess(proc_rank)
459
460 if (down_sample) then
461 call s_initialize_mpi_data_ds(q_cons_temp)
462 else
463 call s_initialize_mpi_data(q_cons_vf)
464 end if
465
466 if (cfl_dt) then
467 write (file_loc, '(I0,A,i7.7,A)') n_start, '_', proc_rank, '.dat'
468 else
469 write (file_loc, '(I0,A,i7.7,A)') t_step_start, '_', proc_rank, '.dat'
470 end if
471 file_loc = trim(restart_dir) // '/lustre_0' // trim(mpiiofs) // trim(file_loc)
472 inquire (file=trim(file_loc), exist=file_exist)
473 if (file_exist .and. proc_rank == 0) then
474 call mpi_file_delete(file_loc, mpi_info_int, ierr)
475 end if
476 if (file_exist) call mpi_file_delete(file_loc, mpi_info_int, ierr)
477 call mpi_file_open(mpi_comm_self, file_loc, ior(mpi_mode_wronly, mpi_mode_create), mpi_info_int, ifile, ierr)
478
479 if (down_sample) then
480 data_size = (m_ds + 3)*(n_ds + 3)*(p_ds + 3)
481 m_glb_save = m_glb_ds + 3
482 n_glb_save = n_glb_ds + 3
483 p_glb_save = p_glb_ds + 3
484 else
485 data_size = (m + 1)*(n + 1)*(p + 1)
486 m_glb_save = m_glb + 1
487 n_glb_save = n_glb + 1
488 p_glb_save = p_glb + 1
489 end if
490
491 ! Resize some integers so MPI can write even the biggest files
492 m_mok = int(m_glb_save, mpi_offset_kind)
493 n_mok = int(n_glb_save, mpi_offset_kind)
494 p_mok = int(p_glb_save, mpi_offset_kind)
495 wp_mok = int(storage_size(0._stp)/8, mpi_offset_kind)
496 mok = int(1._wp, mpi_offset_kind)
497 str_mok = int(name_len, mpi_offset_kind)
498 nvars_mok = int(sys_size, mpi_offset_kind)
499
500 if (bubbles_euler) then
501 do i = 1, sys_size
502 var_mok = int(i, mpi_offset_kind)
503
504 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
505 end do
506 if (qbmm .and. .not. polytropic) then
507 do i = sys_size + 1, sys_size + 2*nb*nnode
508 var_mok = int(i, mpi_offset_kind)
509
510 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
511 end do
512 end if
513 else
514 if (down_sample) then
515 do i = 1, sys_size
516 var_mok = int(i, mpi_offset_kind)
517
518 call mpi_file_write_all(ifile, q_cons_temp(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
519 end do
520 else
521 do i = 1, sys_size
522 var_mok = int(i, mpi_offset_kind)
523
524 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
525 end do
526 end if
527 end if
528
529 if (bubbles_lagrange) then
530 block
531 real(stp), allocatable :: beta_ones(:,:,:)
532 integer :: jj, kk, ll
533 allocate (beta_ones(0:m,0:n,0:p))
534 do ll = 0, p
535 do kk = 0, n
536 do jj = 0, m
537 beta_ones(jj, kk, ll) = 1.0_stp
538 end do
539 end do
540 end do
541 call mpi_file_write_all(ifile, beta_ones, data_size*mpi_io_type, mpi_io_p, status, ierr)
542 deallocate (beta_ones)
543 end block
544 end if
545
546 call mpi_file_close(ifile, ierr)
547 else
548 call s_initialize_mpi_data(q_cons_vf)
549
550 if (cfl_dt) then
551 write (file_loc, '(I0,A)') n_start, '.dat'
552 else
553 write (file_loc, '(I0,A)') t_step_start, '.dat'
554 end if
555 file_loc = trim(restart_dir) // trim(mpiiofs) // trim(file_loc)
556 inquire (file=trim(file_loc), exist=file_exist)
557 if (file_exist .and. proc_rank == 0) then
558 call mpi_file_delete(file_loc, mpi_info_int, ierr)
559 end if
560 call mpi_file_open(mpi_comm_world, file_loc, ior(mpi_mode_wronly, mpi_mode_create), mpi_info_int, ifile, ierr)
561
562 data_size = (m + 1)*(n + 1)*(p + 1)
563
564 ! Resize some integers so MPI can write even the biggest files
565 m_mok = int(m_glb + 1, mpi_offset_kind)
566 n_mok = int(n_glb + 1, mpi_offset_kind)
567 p_mok = int(p_glb + 1, mpi_offset_kind)
568 wp_mok = int(storage_size(0._stp)/8, mpi_offset_kind)
569 mok = int(1._wp, mpi_offset_kind)
570 str_mok = int(name_len, mpi_offset_kind)
571 nvars_mok = int(sys_size, mpi_offset_kind)
572
573 if (bubbles_euler) then
574 do i = 1, sys_size
575 var_mok = int(i, mpi_offset_kind)
576
577 disp = m_mok*max(mok, n_mok)*max(mok, p_mok)*wp_mok*(var_mok - 1)
578
579 call mpi_file_set_view(ifile, disp, mpi_io_p, mpi_io_data%view(i), 'native', mpi_info_int, ierr)
580 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
581 end do
582 if (qbmm .and. .not. polytropic) then
583 do i = sys_size + 1, sys_size + 2*nb*nnode
584 var_mok = int(i, mpi_offset_kind)
585
586 disp = m_mok*max(mok, n_mok)*max(mok, p_mok)*wp_mok*(var_mok - 1)
587
588 call mpi_file_set_view(ifile, disp, mpi_io_p, mpi_io_data%view(i), 'native', mpi_info_int, ierr)
589 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
590 end do
591 end if
592 else
593 do i = 1, sys_size
594 var_mok = int(i, mpi_offset_kind)
595
596 disp = m_mok*max(mok, n_mok)*max(mok, p_mok)*wp_mok*(var_mok - 1)
597
598 call mpi_file_set_view(ifile, disp, mpi_io_p, mpi_io_data%view(i), 'native', mpi_info_int, ierr)
599 call mpi_file_write_all(ifile, mpi_io_data%var(i)%sf, data_size*mpi_io_type, mpi_io_p, status, ierr)
600 end do
601 end if
602
603 if (bubbles_lagrange) then
604 block
605 real(stp), allocatable :: beta_ones(:,:,:)
606 integer :: jj, kk, ll
607 allocate (beta_ones(0:m,0:n,0:p))
608 do ll = 0, p
609 do kk = 0, n
610 do jj = 0, m
611 beta_ones(jj, kk, ll) = 1.0_stp
612 end do
613 end do
614 end do
615 var_mok = int(sys_size + 1, mpi_offset_kind)
616 disp = m_mok*max(mok, n_mok)*max(mok, p_mok)*wp_mok*(var_mok - 1)
617 call mpi_file_set_view(ifile, disp, mpi_io_p, mpi_io_data%view(1), 'native', mpi_info_int, ierr)
618 call mpi_file_write_all(ifile, beta_ones, data_size*mpi_io_type, mpi_io_p, status, ierr)
619 deallocate (beta_ones)
620 end block
621 end if
622
623 call mpi_file_close(ifile, ierr)
624 end if
625#endif
626
627 if (bc_io) then
628 if (igr) then
629 call s_write_parallel_boundary_condition_files(q_cons_vf, bc_type)
630 else
631 call s_write_parallel_boundary_condition_files(q_prim_vf, bc_type, q_t_sf)
632 end if
633 end if
634
635 end subroutine s_write_parallel_data_files
636
637 !> Computation of parameters, allocation procedures, and/or any other tasks needed to properly setup the module
639
640 character(LEN=len_trim(case_dir) + 2*name_len) :: file_loc
641 character(len=15) :: temp
642 character(LEN=1), dimension(3), parameter :: coord = (/'x', 'y', 'z'/)
643 logical :: dir_check
644 integer :: i, iu
645 integer :: m_ds, n_ds, p_ds
646
647 if (parallel_io .neqv. .true.) then
648 write (t_step_dir, '(A,I0,A)') '/p_all/p', proc_rank, '/0'
649 t_step_dir = trim(case_dir) // trim(t_step_dir)
650
651 if (old_grid .neqv. .true.) then
652 file_loc = trim(t_step_dir) // '/'
653
654 call my_inquire(file_loc, dir_check)
655
656 if (dir_check) call s_delete_directory(trim(t_step_dir))
657
658 call s_create_directory(trim(t_step_dir))
659 end if
660
662 else
663 write (restart_dir, '(A)') '/restart_data'
664 restart_dir = trim(case_dir) // trim(restart_dir)
665
666 if ((old_grid .neqv. .true.) .and. (proc_rank == 0)) then
667 file_loc = trim(restart_dir) // '/'
668 call my_inquire(file_loc, dir_check)
669
670 if (dir_check) call s_delete_directory(trim(restart_dir))
671 call s_create_directory(trim(restart_dir))
672 end if
673
674 call s_mpi_barrier()
675
677 end if
678
679 open (newunit=iu, file='indices.dat', status='unknown')
680
681 write (iu, '(A)') "Warning: The creation of file is currently experimental."
682 write (iu, '(A)') "This file may contain errors and not support all features."
683
684 write (iu, '(A3,A20,A20)') "#", "Conservative", "Primitive"
685 write (iu, '(A)') " "
686 do i = eqn_idx%cont%beg, eqn_idx%cont%end
687 write (temp, '(I0)') i - eqn_idx%cont%beg + 1
688 write (iu, '(I3,A20,A20)') i, "\alpha_{" // trim(temp) // "} \rho_{" // trim(temp) // "}", &
689 & "\alpha_{" // trim(temp) // "} \rho"
690 end do
691 do i = eqn_idx%mom%beg, eqn_idx%mom%end
692 write (iu, '(I3,A20,A20)') i, "\rho u_" // coord(i - eqn_idx%mom%beg + 1), "u_" // coord(i - eqn_idx%mom%beg + 1)
693 end do
694 if (eqn_idx%E /= 0) write (iu, '(I3,A20,A20)') eqn_idx%E, "\rho U", "p"
695 do i = eqn_idx%adv%beg, eqn_idx%adv%end
696 write (temp, '(I0)') i - eqn_idx%cont%beg + 1
697 write (iu, '(I3,A20,A20)') i, "\alpha_{" // trim(temp) // "}", "\alpha_{" // trim(temp) // "}"
698 end do
699 if (chemistry) then
700 do i = 1, num_species
701 write (iu, '(I3,A20,A20)') eqn_idx%species%beg + i - 1, "Y_{" // trim(species_names(i)) // "} \rho", &
702 & "Y_{" // trim(species_names(i)) // "}"
703 end do
704 end if
705
706 write (iu, '(A)') ""
707 call write_range(eqn_idx%cont%beg, eqn_idx%cont%end, " Continuity")
708 call write_range(eqn_idx%mom%beg, eqn_idx%mom%end, " Momentum")
709 call write_range(eqn_idx%E, eqn_idx%E, " Energy/Pressure")
710 call write_range(eqn_idx%adv%beg, eqn_idx%adv%end, " Advection")
711 call write_range(eqn_idx%bub%beg, eqn_idx%bub%end, " Bubbles")
712 call write_range(eqn_idx%stress%beg, eqn_idx%stress%end, " Stress")
713 call write_range(eqn_idx%int_en%beg, eqn_idx%int_en%end, " Internal Energies")
714 call write_range(eqn_idx%xi%beg, eqn_idx%xi%end, " Reference Map")
715 call write_range(eqn_idx%B%beg, eqn_idx%B%end, " Magnetic Field")
716 call write_range(eqn_idx%c, eqn_idx%c, " Color Function")
717 call write_range(eqn_idx%species%beg, eqn_idx%species%end, " Chemistry")
718
719 close (iu)
720
721 if (down_sample) then
722 m_ds = int((m + 1)/3) - 1
723 n_ds = int((n + 1)/3) - 1
724 p_ds = int((p + 1)/3) - 1
725
726 allocate (q_cons_temp(1:sys_size))
727 do i = 1, sys_size
728 allocate (q_cons_temp(i)%sf(-1:m_ds + 1,-1:n_ds + 1,-1:p_ds + 1))
729 end do
730 end if
731
732 contains
733
734 subroutine write_range(beg, end, label)
735
736 integer, intent(in) :: beg, end
737 character(*), intent(in) :: label
738
739 if (beg /= 0) write (iu, '("[",I0,",",I0,"]",A)') beg, end, label
740
741 end subroutine write_range
742
744
745 !> Resets s_write_data_files pointer
747
748 integer :: i
749
750 s_write_data_files => null()
751
752 if (down_sample) then
753 do i = 1, sys_size
754 deallocate (q_cons_temp(i)%sf)
755 end do
756 deallocate (q_cons_temp)
757 end if
758
759 end subroutine s_finalize_data_output_module
760
761end module m_data_output
Interface for the conservative data.
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_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.
real(wp), dimension(:), allocatable, public gammas
real(wp), dimension(:), allocatable, public gs_min
real(wp), dimension(:), allocatable, public qvs
subroutine, public s_compute_pressure(energy, alf, dyn_p, pi_inf, gamma, rho, qv, rhoyks, pres, t, stress, mom, g, pres_mag)
Compute the pressure from the appropriate equation of state.
real(wp), dimension(:), allocatable, public pi_infs
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).